6

How can I test if exit is clean in a shutdown function in PHP?

By clean exit I mean that the script was not terminated due to an error.

agsamek
  • 8,734
  • 11
  • 36
  • 43
  • By "clean exit" do you mean that the shutdown function should check if the script ended because it reached the end of the code and not because it encountered an error? – Bailey Parker Aug 30 '11 at 10:07
  • Interestingly, I was fooling around trying to come up with something to answer this cryptic question, and I found that `debug_backtrace()` doesn't trace beyond the registered shutdown function when called from within it. – Dan Lugg Aug 30 '11 at 10:12
  • 1
    the `exit()` function in php can have a parameter as status code. This code is usable in another script, e.g. when you run your script with `exec()` or `passthru()` (or even when you use multiple threads). – y_a_v_a Aug 30 '11 at 10:16

4 Answers4

7

Its a good question, for the moment I only have this idea: register a shutdown function like this:

function shutdown() {
    if (defined('END_REACHED') {
        echo 'Script executed with no error', PHP_EOL;
    }
}

register_shutdown_function('shutdown');

With auto_append_file add an additional file to the very end of every script execution which sets an constant.

Your auto_append_file.php content:

define('END_REACHED', TRUE);

In case you dont want to edit the php.ini you could do check error_get_last() or $php_errormsg in your register shutdown function!

powtac
  • 40,542
  • 28
  • 115
  • 170
  • +1 but I would prefer a solution that doesn't require php.ini modification, if possible. – agsamek Aug 30 '11 at 10:21
  • 1
    `auto_append_file` can be modified with .htaccess as well. – powtac Aug 30 '11 at 10:30
  • I don't understand why this would do what you suggest - unless you conditionally include the file it will be processed in the implicit main scope therefore the definition will take effect immediately the code is parsed - not when execution completes - and what's the difference between using an include construct and setting a flag/definition inline? – symcbean Aug 30 '11 at 10:53
  • The define of END_REACHED is always appended at the very end of every script. As far as I understand, the register_shutdown_function is called after everything was processed well or when an error occurs. In the first case the define was reached in the second case not. – powtac Aug 30 '11 at 10:58
1

A call to error_get_last() can tell you if or which error occurred. If the function returns NULL, it is a clean shutdown.

Mobiletainment
  • 22,201
  • 9
  • 82
  • 98
Ferdy Pruis
  • 1,073
  • 8
  • 9
1

There are lots of reasons a script might terminate prematurely. There is no generic solution. The only errors which will cause the script to terminate prematurely are fatal errors - and in most cases a shutdown function will not run after a fatal error, similarly a custom error handler will only reliably see non-fatal errors. Then there's the option of setting up signal handlers - but again they only see some of the story.

The big question of course, is what do you want to do with this information in the shutdown function?

The only reliable way to determine of your logic completed as expected is to raise a semaphore when this happens and check it in the shutdown function.

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • Someone upvoted this today - the information above was correct in 2011, but nowadays its a lot more difficult to crash a syntactically correct PHP script without calling the shutdown function. – symcbean Jan 15 '21 at 17:52
0

I've ported (for PHP 5.3) ezcExecution component which handles this nicely. See https://github.com/sobstel/Execution. Basically you need to inform lib that exit was clean (by calling Execution::cleanExit(). Otherwise it means exit was not clean. Simple like that.

sobstel
  • 1,432
  • 16
  • 11