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);
开发者_如何学Python 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
, and E_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_ERROR
is only thrown while the PHP interpreter is bootstrapping itself, it occurs before a shutdown function can be registered and cannot be trapped.
I wasn't able to find anything that would allow you to redirect stderr with an approach like the one you are using.
However, you could perhaps use ini_set('error_log', $some_log_path)
in your child and then read the file if the child crashed to determine the error message?
Failing that, you could rewrite your code to invoke a separate single-test-runner PHP wrapper via proc_open
and use the shell to send stderr to somewhere sane.
精彩评论