Skip to content

Allow throwing exception while loading parent class #4697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

nikic
Copy link
Member

@nikic nikic commented Sep 11, 2019

This is a fix for symfony/symfony#32995.

The behavior is:

  • Throwing exception when loading parent/interface is allowed (and we will also throw one if the class is simply not found).
  • If this happens, the bucket key for the class is reset, so it's possibly to try registering the same class again.
  • However, if the class has already been used due to a variance obligation, the exception is upgraded to a fatal error, as we cannot safely unregister the class stub anymore.

cc @nicolas-grekas

@nikic nikic force-pushed the symfony-class-loading branch from 45291fc to 91b0a0d Compare September 11, 2019 15:40
@nikic nikic changed the title Allow throwing exception while loading parent class [WIP] Allow throwing exception while loading parent class Sep 11, 2019
@nicolas-grekas
Copy link
Contributor

Awesome, thank you! I'll try this once its merged if you don't mind :)

@nikic nikic changed the title [WIP] Allow throwing exception while loading parent class Allow throwing exception while loading parent class Sep 12, 2019
@nikic
Copy link
Member Author

nikic commented Sep 12, 2019

@dstogov Can you please take a look at this? I don't like doing this, but ability to throw exceptions for undefined parent/interface is important for Symfony to support their current implementation of optional dependencies, which they cannot easily remove.

Copy link
Member

@dstogov dstogov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood the incompatibility introduced in PHP-7.4 and agree it should be fixed.
Missed "parent" class should throw exception. I don't see a problem extending this to interfaces.

The patch slightly increase complexity of already extremely complex "inheritance + type & variance check" algorithm. It's OK to merge it, if it does everything right.

Class A does not exist
Class A does not exist

Fatal error: During inheritance of B: Uncaught Exception: Class A does not exist in %s:%d
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's very unclear, why two times we got exceptions and now a fatal error.

@@ -30,6 +30,8 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
#define zend_do_inheritance(ce, parent_ce) \
zend_do_inheritance_ex(ce, parent_ce, 0)

/* TODO: Merge these in master -- only here to prevent ABI change. */
ZEND_API int zend_do_link_class_ex(zend_class_entry *ce, zend_string *lc_parent_name);
ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this ABI break is not a problem before 7.4 GA.

@@ -3731,7 +3731,9 @@ static void preload_link(void)
} else {
CG(zend_lineno) = ce->info.user.line_start;
}
zend_do_link_class(ce, NULL);
if (zend_do_link_class_ex(ce, NULL) == FAILURE) {
ZEND_ASSERT(0 && "Class linking failed?");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is't possible to not preload just this class?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not easily, because then other classes also may not be preloaded because of that. The only way in which class linking can fail (without a fatal error I mean) is if parent/interface is missing. However, we have ensured beforehand that they exist, so this cannot happen, which is why this assertion is here.

@nikic
Copy link
Member Author

nikic commented Sep 12, 2019

Merged as 4b9ebd8 with _ex function removed and a slightly more explicit error message (so there is at least something to Google...)

@nicolas-grekas After this change, I only have three remaining test failures on symfony:

Symfony\Component\Filesystem\Tests\FilesystemTest::testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy
Symfony\Component\Lock\Tests\Store\FlockStoreTest::testBlockingLocks
Symfony\Component\Lock\Tests\Store\SemaphoreStoreTest::testBlockingLocks

@nikic nikic closed this Sep 12, 2019
nicolas-grekas added a commit to symfony/symfony that referenced this pull request Sep 19, 2019
…-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

Re-enable previously failing PHP 7.4 test cases

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #32995
| License       | MIT
| Doc PR        | -

The remaining PHP 7.4 issue has been fixed by Nikita in php/php-src#4697
This should be green once Travis updates their php7.4snapshot

Commits
-------

9e4e191 Re-enable previously failing PHP 7.4 test cases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants