Archive for November, 2008

The Infamous 3221225477 and Autoloading

November 25, 2008

Parent: child process exited with status 3221225477 — Restarting.

It wasn’t until I ran into it myself that I realized the fear that this error message strikes in the hearts of many.  It shows up in the apache error logs and is accompanied by an apache process dying.  The user sees a blank screen or an error message, and the developer is left scratching is head and wading through page after page of google hits with no solutions…

It sounds like there may be a number of causes, but I found one: using call_user_func_array() to call static methods of not-yet-loaded classes in PHP.  In my case, the code looked something like this:

/**
 * Delegates all function calls to static methods of $this->class.
 *
 * @param string $name static method name
 * @param array $arguments all arguments
 * @return mixed
 */
public function __call($name, $arguments)
{
    return call_user_func_array(array($this->class, $name), $arguments);
}

In my case, $this->class held the string “DatasetPeer” which was the name of a class.  The class was typically loaded using autoloading, and at the point in the code where this failed it had not yet been referenced, and so had not been loaded.  Apparently (at least in my version of php) call_user_func_array() called in this manner does not autoload the class, but rather crashes the apache process. I would assume that call_user_func() works similarly.

The solution was to load the class, and the easist way I could think of to do that without having to actually invoke a method on the class was to use reflection:

/**
 * Delegates all function calls to static methods of $this->class.
 *
 * @param string $name static method name
 * @param array $arguments all arguments
 * @return mixed
 */
public function __call($name, $arguments)
{
    // Force auto-loading of the class.  If is has not loaded yet, then
    // call_user_func_array will cause a nasty crash
    $rc = new ReflectionClass($this->class);

    return call_user_func_array(array($this->class, $name), $arguments);
}

I will probably now use the ReflectionClass object $rc to invoke the method, foregoing call_user_func_array() completely, but I note that this one change was sufficient to solve the problem.