-
Notifications
You must be signed in to change notification settings - Fork 3k
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
class_exist bool autoload should be false if __autoload function doesn't... #959
Conversation
…n't exist class_exist:: bool autoload should be false if __autoload function doesn't exist issue facebook#947
Hi @ellisium, before we can look at this, we need you to fill out a Contributor License Agreement as it doesn't appear you've ever contributed to a Facebook OSS project before: https://developers.facebook.com/opensource/cla Please let us know when you've done so and we'll review this. Thanks! |
hi @scannell, that's signed |
Thanks for filling that out. See my comment on the commit itself -- tests are needed to verify this fixes the issue. |
Could you explain me more what you want and where? |
hi, sorry I can't reproduce the stackoverflow error with a simple test case. |
Hi @ellisium, we're not going to take this as-is (no tests, no verification this doesn't otherwise break spl_autoload and other named functions) so closing this PR. If someone wants to take another look at this, feel free. |
hi @scannell, finally I've worked on test case this weekend, and got it. Is it possible to reopen this PR or I've to do a new one? and how add the test case? |
Hi Eric - I fixed the reason you'd see this with Drupal (should be pushed shortly) by reporting that we implement filter and SPL so this should be lower priority for now. We won't take this version of the fix because it puts an expensive function_exists check on a very common path which is unnecessary the vast majority of the time and will affect overall performance of HHVM. If you want to pursue this, from an internal code review discussion of this: First, the check should go on the slow path. In other words, wait until we decide we actually need to autoload before doing any special-case logic. Second, you need to figure out what zend does so we can mirror autoload functionality accurately. Does it disable all autoloading from within any autoload handler? Does it just disable autoloading for any class which is actively being autoloaded? Can you spl_autoload a class which is already being __autoloaded? I'm also assuming it has nothing to do with class_exists, but rather autoloading in general; but you should check that too. |
ok if that's affecting performance of HHVM, it's logical to search another way. |
@scannell, I've traced the actual process with coding error omitting autoload=false if (m_handlers.isNull() && !forceSplStack) { autoloadHandler return false so the function loadMissingClass falls in loop and produce finally the stackoverflow. my patch use expensive function_exists(s___autoload), it's true but autoloader use it also and anyway autoloader should not be called in this case, I think to call autoloader is more expensive? no? For me, it's really a problem about class_exists and not like you say about autoloader in general. |
It's fine for this particular case to be expensive. (If we really are going to invoke the autoloader, it's going to be expensive anyway, you are definitely correct.) The problem is that To put it another way, in a PHP application where there is never any autoloaded code and no autoload handler is ever registered ( |
effectively, I'm completely agree and anyway test function_exists(s___autoload) should be in getClass and not in classExists so this PR is wrong. in getClass could be : |
Does Zend allow |
In my test case, Zend doesn't allow it. Server crash when calling a different class inside spl_autoload_register function |
Where is the test case? It would be helpful to see what is going on here. You should also try just chaining __autoload together -- class A autoloads class B which has to autoload class C. That seems like something Zend should allow as long as A != B != C? |
Checking Also, come to think of it, is checking |
you can find tests case here https://github.com/ellisium/hiphop-php/tree/patch-1/hphp/test/slow/autoload "Does Zend allow __autoload for a different class to be called inside an spl_autoload_register handler? (It may not be correct to disallow autolading from inside an autoloader.)" "Where is the test case? It would be helpful to see what is going on here. You should also try just chaining __autoload together -- class A autoloads class B which has to autoload class C. That seems like something Zend should allow as long as A != B != C?" "@ellisium, see #976, more evidence this is really a broader problem with autoloading and not just with class_exists." I confirm AutoloadHandler::s_instance->isRunning() and function_exists, are not the right way. by example that break prestashop autoload |
Any ideas on what we need to do here then? Also, I should add, I'm glad we're making progress here -- thanks for spending time on this. |
I report you my test of today CASE AutoloadHandler::s_instance->isRunning() CASE !function_exists(s__autoload) Do you want I open a new issue about 1-2-3.php test case? "Is the problem that it sets that value before getClass is called the first time to autoload?" Sorry, don't get it. |
Today, I've investigated on joomla problem. So about joomla: |
Joomla classes are defining |
Example is better than words
|
You can edit the ext_spl.h by hand. (We generally only use that script for initial generation, the update hasn't worked in a while; sorry about that.) |
Hi, thx for this fast answer.
|
Two things:
|
thx, it's ok about class now.
|
Not sure. I'd attach gdb and debug it since it's something at the lower level. |
it's ok, sorry my fault. I thought all HPHP class (Array, String, etc) were reset after end of request but I was wrong so my code corrupted memory. |
"that was a big surprise to discover that ZEND allow spl_autoload_register to access a private or protected function loader. You get unpredictable issues when you register a private autoloader like this. The reason you CAN do it is because you are calling spl_autoload_register from within the class itself, ie: Now with an example of using it: This will attempt to include the file ./class_UnknownClass.php require fails and will cause the application to abort immediately. Much much much worse, because this occurred in a private method, you don't get ANY error information[all the require error messages are lost] No line numbers, no idea what the problem is. Even XDebug doesn't help much. With XDebug you can get to the line $myclass=new CoreUnknownClass(); but it can't step into the autoloader since it is private, it will die on that line. As such, even though Zend "allows" this to be done, it does not /support/ it being done - it is an accident - as such I really don't think you should copy this functionality - it's a Zend bug, not a feature. If changing that one word from "private" to "public" will allow the Joomla unit tests to run, then the issue is a Joomla issue - not a hiphop issue. |
@garyamort in latest joomla version, load function has been changed to public. |
To be precise, the fix will treat the call to the autoloader as having been called from the context in which the loader was registered. In general, this is not recommended practice -- and I'd at least be happy to take this code out if the we can all agree that we should not do this and to deprecate the old behavior. PHP Internals is probably the right place for that discussion though. |
@scannell, you're right, we are all agree for to say that access private/protected is wrong way. Before to out it, maybe zend developpers opinion is required. If they keep going in futur with this way, we can't skip it. |
@ellisium Not quite. In the latest Joomla framework there are 3 possible autoload methods in JLoader. 2 are public[load by namespace and load by psr0], load by prefix[the only method I know offhand, which is __autoload] is still private. Load by prefix is a legacy function that will be depreciated at some point, so I'll pull down the code and submit a pull request to make that public later this week. I'm primarily a PHP programmer with a strong background in Joomla! so seeing it at 0% on the latest blog post piqued my interest. :-) My interest in HiphopPHP is actually to compare memory usage for running it on an embedded system[BeagleBoneBlack] since PHP is a rather hefty investment when you only have 512M of memory. I just wanted to make sure you were aware that this functionality is not a Zend "feature" and that it is actually bad coding practice before spending a lot of time trying to replicate Zend's "bug" :-) |
@garyamort, thanks. The effort has already been put in to fix this -- this falls under the case where enough widely-used existing PHP code uses it that we'll have to hold our nose since it's at least somewhat defensible (even if not the best coding practice.) Re: embedded, I believe you will OOM with only 512 MB by default because of the slabs we reserve on startup, although that is configurable. That aside, we've focused our optimization efforts on datacenter-grade servers and definitely (within reason) prioritize reducing CPU usage over reducing RAM usage due to the cost factors involved. This is not to say we wouldn't also welcome contributions to reduce memory usage but it hasn't been an active area of investigation. |
class_exist:: bool autoload should be false if __autoload function doesn't exist
cf issue #947