DEV Community

Chris Armitage
Chris Armitage

Posted on

If you're experimenting with pcntl_signal, don't use sleep()

I've been tinkering with my own PHP micro framework (yes, everyone does, it's a right of passage) and wanted to make some nice queue listener functionality. I've been playing with the likes of AMQP and Kafka, and wanted the listener to shutdown gracefully. I'd never used the pcntl library before, so it seemed like a good time to learn.

This isn't a post about the inner workings of pcntl, but it does reveal a gotcha that caused me do doubt my sanity.

In brief, the pcntl_signal command allows you to intercept a CTRL-C from the command line. You use it like this:

pcntl_signal(SIGINT, function () {
    // This will be executed on a CTRL-C, and the script won't terminate
});
Enter fullscreen mode Exit fullscreen mode

The general goal is you switch to a graceful shutdown state, finish the active queue job, and then terminate. I didn't have any real code behind this, so the job worker was a simple sleep(5) to simulate a real-world process. Everything looked good, but it just would not work. As soon as I tried to terminate the script, it actually terminated, it didn't finish the job. No matter what I fiddled with or changed, it just would not finish that job.

Except.. well... it was doing...

What I hadn't realised was this buried away in the PHP docs

If the call was interrupted by a signal, sleep() returns a non-zero value.

The signal was being picked up by my custom pcntl_signal handler, but it was also immediately ending the sleep command. It was the placeholder code that was failing.

So, if you want to learn pcntl (and I may just post some more about what you can do with it), use a snippet like this:

$now = microtime(true);
$target = $now + 5;

while (microtime(true) <= $target) {
    // noop
}
Enter fullscreen mode Exit fullscreen mode

That will cause your script to wait for 5 seconds and won't be interrupted by the CTRL-C.

Top comments (0)