Created
August 8, 2012 19:18
-
-
Save jsjohnst/3297804 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(ticks = 1); | |
class TimeoutException extends Exception {}; | |
function signal_handler($signal) { | |
throw new TimeoutException(); | |
} | |
pcntl_signal(SIGALRM, "signal_handler", true); | |
pcntl_alarm(1); | |
try { | |
// simulate long executing block | |
while(1) sleep(30); | |
} catch(TimeoutException $e) { | |
echo "Timeout exceeded"; | |
} | |
echo "done"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some more info, because this is one of the highest results on Google for
pcntl_alarm
:declare(ticks = 1);
tells the parser to enable the "tick" event per statement in your code.You must set this, otherwise pcntl_alarm won't get called periodically, and it'll never fire its interrupts.
pcntl_signal(SIGALRM, "signal_handler", true);
sets up a signal that's triggered by SIGALRM (pcntl_alarm). When SIGALRM is triggered, the signal_handler function is called.pcntl_alarm(1);
says to trigger the SIGALRM signal in 1 second. It will only alarm once.In the try/catch block, we're just sleeping for 30 seconds, in an infinite while loop. We won't ever exit until the
TimeoutException
is thrown.What happens, is
pcntl_alarm
fires after one second, andpcntl_signal
firessignal_handler
. This function throws aTimeoutException
. The execution happens in the context of thewhile
loop, so the exception bubbles up into the try/catch statement.The result, is after 1s the application exists.
Some fun things to note:
pcntl_alarm(1);
only causes an interrupt once. You need to call it again to make subsequent interrupts occur.sleep()
can be interrupted by the alarm signal. This is not true for all functions.sleep()
will not resume after the alarm signal. Try replacing thethrow
insidesignal_handler
withecho "derp"; pcntl_alarm(1);
and you'll see "derp" printed every 1 second.declare(ticks = 1)
provides an instruction to the php parser. It will apply to every file after you have set it. This makes the order of file inclusion important. If you don't want it to apply, you can always set it back to 0 at the end of the file you need it in.ticks
is not set (before it's set, or set back to 0), ticks will not be observed because the interrupt events are not written into the opcode. The alarm will only occur after execution returns to a file that hasticks
set.declare(ticks=1)
set (approx 1milmd5
ops in a loop).