22

If I use Ctrl+C to exit a PHP script running in CLI, neither the shutdown functions, nor the destructors of instantiated objects, nor any output buffers are handled. Instead the program just dies. Now, this is probably a good thing, since that's what Ctrl+C is supposed to do. But is there any way to change that? Is it possible to force Ctrl+C to go through the shutdown functions?

More specifically, this is about serialising and saving data on exiting of the script, so it can be reloaded and resumed the next time the script runs. Periodically saving the data could work, but would still lose everything from the last save onward. What other options are there?

Alexander Yancharuk
  • 13,817
  • 5
  • 55
  • 55
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • Have you considered trying Ctrl+Z? I don't know if that works with PHP or not... – Brad Nov 13 '12 at 21:01
  • I'm not sure what Ctrl+Z is supposed to do. I just tried it and it doesn't seem to do anything, other than cause a ^Z character to appear on the next prompt that appears (be it an `fgets(STDIN)` or the new prompt after a Ctrl+C) – Niet the Dark Absol Nov 13 '12 at 21:03
  • I haven't done PHP CLI in a while but is there a way to periodically look grab CLI input and listen for a specific "kill" command and then initiate the deconstructor?? You could also set a "kill" flag in a config file for your script and routinely check for that flag. – Bryan Allo Nov 13 '12 at 21:03
  • 2
    Looks like you're out of luck with Windows: [PHP doesn't support signal handling on Windows. Sorry.](http://stackoverflow.com/a/3333291/895378) –  Nov 13 '12 at 22:44

3 Answers3

12

Obviously PCNTL is *nix only, but ... You can register handlers for all the individual signals for a more robust solution, but specifically to do something when a CTL+C interrupt is encountered:

<?php
declare(ticks = 1);

pcntl_signal(SIGINT, function() {
    echo "Caught SIGINT\n";
    die;
});

while (true) {
    // waiting for your CTRL+C
}
2

Take a look at PCNTL especially pcntl_signal()

1

I contrast to the answer by @rdlowrey, I would avoid a plain while(true) as well as that die/exit in the pcntl_signal function as it does not allow handling things after the loop has been user-interrupted.

Instead, I’ld like to suggest the following, more logic solution:

declare(ticks = 1);

$running = true;

pcntl_signal(SIGINT, function() {
    global $running;
    $running = false;
});

while($running)
{
    echo('running…'.PHP_EOL);
}

echo(PHP_EOL.'User interrupted the loop. Shutting down cleanly.'.PHP_EOL);
exit();
e-sushi
  • 13,786
  • 10
  • 38
  • 57