Ok, so I've been trying to get Process Signals
to work with PHP
scripts. I've run into a lot of stuff where I am just not sure what is going on, and I feel like the documentation doesn't do a very good job of explaining it.
So let's say I follow the example on registering signals:
<?php
// tick use required as of PHP 4.3.0
declare(ticks = 1);
// signal handler function
function sig_handler($signo)
{
switch ($signo) {
case SIGTERM:
// handle shutdown tasks
exit;
break;
case SIGHUP:
// handle restart tasks
break;
case SIGUSR1:
echo "Caught SIGUSR1...\n";
break;
default:
// handle all other signals
}
}
echo "Installing signal handler...\n";
// setup signal handlers
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");
// or use an object, available as of PHP 4.3.0
// pcntl_signal(SIGUSR1, array($obj, "do_something"));
echo"Generating signal SIGTERM to self...\n";
// send SIGUSR1 to current process id
posix_kill(posix_getpid(), SIGUSR1);
echo "Done\n";
?>
However, within my sig_handler
function, I add an exit(1)
at the end. Will the echo "Done\n";
still be executed? I have attempted something similar, albeit in a class structure, and it was- only before my sig_handler
ever got called.
My class __construct
calls the function registerSignals
:
private function registerSignals(){
if(function_exists("pcntl_signal")){
//call_user_func([$this, "sigintCleanup"]);
pcntl_signal(SIGINT, [$this, "sigintCleanup"]);
pcntl_signal(SIGTERM, [$this, "sigtermCleanup"]);
pcntl_signal(SIGHUP, [$this, "sighupCleanup"]);
pcntl_signal(SIGUSR1, [$this, "sigusr1Cleanup"]);
}
}
protected function sigintCleanup(){
echo "In SIGINT cleanup\n";
$this->cleanup();
}
protected function sigtermCleanup(){
echo "In SIGTERM cleanup\n";
$this->cleanup();
}
protected function sighupCleanup(){
echo "In SIGHUP cleanup\n";
$this->cleanup();
}
protected function sigusr1Cleanup(){
echo "In SIGUSR1 cleanup\n";
$this->cleanup();
}
protected function cleanup(){
echo "Shutting down\n";
exit(1);
}
And then within my testing of this process, I do some simple sleep
s and echo
s (start
is just a function called after the construction and signal registration is finished):
function start(){
echo "-- Testing the test script --\n";
sleep(10000);
echo "given how ticks work, this might not be called...\n";
echo "\nAfter sleep... this should not be executed if there was a signal interrupt.\n";
}
So I use ctl-c
during the sleep
. My result?
-- Testing the test script --
^Cgiven how ticks work, this might not be called...
After sleep... this should not be executed if there was a signal interrupt.
In SIGINT cleanup
Shutting down
As you can see from my echo
s, I kinda figured maybe the way ticks work was responsible for finishing the start
function before handling the signal. I still think this might be the case. The truth is, I just don't know.
I do declare ticks
at the top of my program:
declare(ticks = 1);
Not handling signals immediately is causing problems for me. What if, for instance, I had this bit of code in my start
function (and I've tested this)?
$count = 0;
while(true){
count++;
echo "count\n";
sleep(5);
}
Even if my cleanup
function has an exit
, I never reach that because the SIGINT
just knocks me out of sleep
, and I continue in the loop and begin sleep
ing again.
So here's my question: How does signal
handling work in PHP
? How can I guarantee that when I get a signal, it is handled immediately? I don't just want some piece of code that will fix this, I would like an explanation (or at least a link to a good one and a summary).
PHP version: 5.4.22
OS: Ubuntu 12.10