I’ve already learned that you can’t catch PHP Fatal Errors, and your script will terminate about as soon as it hits one. I’m running a large PHP test suite (not PHPUnit, but a custom solution) on a CI server, and want to have the test pass/failures to be reported in JUnit output format.
Since way too many things in PHP are “Fatal Errors”, I don’t want the Fatal Error to end my test run, so my solution was to use forking, something like this:
foreach($tests as $test) {
$pid = pcntl_fork();
if ($pid) {
$test->run();
$test->write_junit($some_file_name);
}
else {
pcntl_wait($status);
if ($status) { //fatal error
// from here we have no data about why it
// crashed, since that was in the child's memory
}
}
}
My idea was to close the STDERR in the child and have it send it’s standard error to a pipe that the parent can read and save the error data into the JUnit file, but now I don’t know if that’s possible. Can you change the file for STDERR? Basically, what I want to do is like popen but without the exec() step.
Can I get the output of a child process after it died of a PHP Fatal Error?
You can register a shutdown function in the child process and check the last error when it’s called. If there’s an error that matches one of the fatal types (
E_ERROR,E_COMPILE_ERROR,E_CORE_ERROR, andE_PARSE), write it into the JUnit file. While you cannot recover from a fatal error, your shutdown function is still called.Update: As Pacerier points out in the comments, since
E_CORE_ERRORis only thrown while the PHP interpreter is bootstrapping itself, it occurs before a shutdown function can be registered and cannot be trapped.