-
-
Save jsjohnst/3297804 to your computer and use it in GitHub Desktop.
<?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"; |
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, and pcntl_signal
fires signal_handler
. This function throws a TimeoutException
. The execution happens in the context of the while
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.- For files where
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. - Where ticks have been enabled, sub-routines inside other classes or files will be interrupted by the alarm event, and resume cleanly.
- In my benchmarking, there was no discernible performance hit with
declare(ticks=1)
set (approx 1milmd5
ops in a loop).
How after hour?
Hi,
can you please explain what the code does.
thank you