Timing your signals

int pcntl_alarm ( int seconds)

Basic signal processing like we have been using so far is a great way to make your scripts respond to signals with a custom function. However, another cool use of signals is as timers - you can ask the system to tell your script when a certain number of seconds have passed. This is helpful for two reasons: it allows your script to execute freely, and get interrupted after a certain number of seconds to perform some maintenance (perhaps repeatedly), and it also allows you to force a timeout on a function call. This is done using the function pcntl_alarm() and the SIG_ALRM signal: pcntl_alarm() takes the number of seconds to wait as its only parameter, and when that number of seconds has expired your program will be sent the SIG_ALRM signal.

What is important about this is that pcntl_alarm() is non-blocking - that is, your call to pcntl_alarm() returns immediately, and the program will continue processing other instructions. As soon as the SIG_ALRM is received, control will jump to your signal handling function where you can perform custom behaviour. You can do whatever you please here to respond to the alarm, but once you are done (provided you do not exit the script) control is passed back to the previous location in the script.

These alarms are very helpful for performing non-linear processing inside your scripts. For example, you might have produced a mail program where you want the user to be able to browse around their mail box and write emails, and yet every 60 seconds the program should check for new emails. This last function, checking for new emails, is where pcntl_alarm() would come in.

This next script goes into the same infinite loop as before, but will print a message out every three seconds. Note that the alarm set up by pcntl_alarm() only occurs once - you need to reset the alarm once it has been signalled, as in the script:

<?php
    declare(ticks = 1);

    function signal_handler($signal) {
        print "Caught SIGALRM\n";
        pcntl_alarm(3);
    }

    pcntl_signal(SIGALRM, "signal_handler", true);
    pcntl_alarm(3);

    while(1) {
        //
    }
?>

There are three particularly interesting extras available when using pcntl_alarm() that make it more powerful:

  1. You may only have one alarm set up at one time. If you call pcntl_alarm() before the previous alarm was reached, the new alarm will replace the old alarm and pcntl_alarm() will return the number of seconds that were remaining before the previous alarm was sounded.

  2. If you call pcntl_alarm() and pass 0 as the number of seconds to wait, this clears any current alarm and again returns the number of seconds left on the previous alarm.

  3. Any alarm that comes in will abort a system call, including snapping out of a sleep() call.

 

Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Getting into multiprocessing >>

Previous chapter: Taking control of PHP

Jump to:

 

Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.