开发者

Getting the output of a child process's "PHP Fatal Error"

开发者 https://www.devze.com 2023-02-20 04:37 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消