Lemme begin by giving a basic description of the code I have. I start off with a main parent process (NOTE: I am not showing all functions for simplicity. Let me know if you need me to expand at any point):
declare(ticks=1);
pcntl_signal(SIGHUP, array('forker', 'restartSignalHandler'));
if(forker_is_not_running()){
new Forker();
}
class Forker {
private $active_forks = array();
private $parent_pid = null;
public function __construct(){
$this->parent_pid = getmypid();
$this->create_fork();
$this->wait_for_active();
}
public function wait_for_active(){
while(!empty($this->active_forks)){
foreach($this->active_forks as $k=>$fork){
if($this->fork_no_longer_running($fork)){
unset($this->active_forks[$k]);
}
}
}
}
// Pseudo code
public function fork_no_longer_running($pid){
// return true if 'ps -elf | grep $pid' doesn't returns only the grep command
// else return false (aka the fork is still running)
}
public function create_fork(){
$pid = pcntl_fork();
if($pid == -1){
posix_kill($this->parent_pid, SIGTERM);
} else if($pid){
// add the pid to the current fork
$this->active_forks[] = $pid;
} else {
// Run our process
pcntl_exec('/usr/bin/php', array('/domain/dev/www/index.php','holder','process'));
exit(0);
}
}
public function restartSignalHandler(){
$forks = $this->active_forks;
foreach($forks as $pid){
$this->create_fork();
posix_kill($pid, SIGINT);
}
}
}
class holder {
public function process(){
$x = new Processor();
}
}
class Processor {
public function __construct(){
pcntl_signal(SIGINT, array($this, "shutdownSignalHandler"));
}
public function shutdownSignalHandler(){
echo "Shutting down";
exit;
}
}
Here is what is happening:
Lemme know if that needs more details/doesn't make sense. I can't figure out why the first time it would properly kill the children, but the 2nd time it doesn't.
The even WEIRDER part is that when I change it so that I change my restart handler so that it keeps trying to kill the child with a SIGINT, it fails each time, but when I send it a SIGKILL command it kills the child process:
if($time_passed > 60){
posix_kill($pid, SIGKILL);
}
I need the child to be able to be killed by SIGINT in order to handle it properly. I don't want to just SIGKILL it. Is there any reason as to why the 2nd time around SIGINT wouldn't work, but SIGKILL will?
First of all, you do not need to fork. Your code does an exec inside the child, you could basically just run the exec whithout forking, and the OS will spawn your command as a child. If you want to use fork, just include
the file in the child rather than execing.
public function create_fork(){
//no need to actually fork!
pcntl_exec('/usr/bin/php', array('/domain/dev/www/index.php','holder','process'));
}
//if you want to fork, better do it like this :
public function create_fork(){
$pid = pcntl_fork();
if($pid == -1){
posix_kill($this->parent_pid, SIGTERM);
} else if($pid){
// add the pid to the current fork
$this->active_forks[] = $pid;
} else {
// Run our process
include '/domain/dev/www/index.php';
SomeClass::someMethod();
exit(0);
}
}
Also, when using fork, you need to waitpid
for the children. So, in your code you need to insert something like :
//somewhere in a loop :
$pidOfExittedChild = pcntl_waitpid (-1, $status, WNOHANG);
if ($pidOfExittedChild) {
//a child has exitted, check its $status and do something
}
Check more at : http://php.net/manual/en/function.pcntl-waitpid.php
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With