views:

318

answers:

3

I ran across an interesting issue today. We have an application that utilizes Zend Frameworks caching functionality. A request to this application typically calls a factory method using the following line

$result =  call_user_func_array(array("myclass", "factory"), array($id));

The idea is to return an object from the factory method that we can access later on. When we implemented a caching feature, this call just, well, dies. No errors, just a white screen. Nothing in the error log. We can error log the line before ok, but trying to error_log inside the factory method does nothing.

Interestingly enough, changing the line to :

$result =  call_user_func(array("myclass", "factory"), $id);

fixes the issue.

We've spent a few hours looking around for bug reports and haven't come up with much to explain this behavior. Thoughts anyone?

A: 

Which version of php are you using? There was an issue in combining call_user_func_array with ReflectionClass at one point. I'm not sure if it's fixed yet.

troelskn
we're using 5.2.8
goose77
I'm pretty sure that the issue I'm talking about is older than that.
troelskn
A: 

Is it segfaulting? Check your 'root' apache logs (outside of any virtualhost) and see whats going on. If that thread is segfaulting you may want to persue that on the PHP mailing lists and/or bug tracker.

Alternately you could try running http in single user mode, in GDB, with a debug-compile of php and see if you can capture it, but thats a lot of work :-)

Justin
I've scoured all of my logs, and there are no indications that Apache is segfaulting. I wish I had time to debug apache in single user mode.
goose77
Wait... check that... it did segfault. Off to PHP I go.
goose77
I've run into some hard to debug segfaults in PHP when using autoloading for my classes. Basically, some functions do not trigger the autoloader if a class does not exist, don't even throw a fatal error, and proceed with reckless abandon. A good example is using method_exists() with a string representing a class name that has not yet been included == segfault.
jason
+1  A: 

I have had issues like this that came down to __autoload not firing properly when a not-yet-loaded class was invoked through a PHP command. No other strategy than dumb trial and error for it as far as I know, just try if a line explicitly invoking the class before the PHP command solves it for you.

$dummy = new MyClassName;
call_user_func_array(array('MyClassName', 'method'), array($id));
unset($dummy);
dyve
My theory goes that call_user_func_array is being a little more reckless (for lack of a better term) when trying to make the call. It would be interesting to see the source of the two functions to compare them. I'm going to submit a bug report to PHP for this issue and see what they say.
goose77
Calling `__autoload` directly, or at least `class_exists` (with the second param true, which is the default) would be a cheaper way to trigger the autoloader. That way you don't waste memory instantiating an instance of the class.
jason