-
-
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 thethrowinsidesignal_handlerwithecho "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
ticksis 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 hasticksset. - 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 1milmd5ops in a loop).
How after hour?
Hi,
can you please explain what the code does.
thank you