【问题标题】:Subsequent pcntl_signal signals not kicking off handler随后的 pcntl_signal 信号未启动处理程序
【发布时间】:2012-03-12 21:54:59
【问题描述】:

首先我要对我拥有的代码进行基本描述。我从一个主要的父进程开始(注意:为简单起见,我没有显示所有功能。如果您需要我随时扩展,请告诉我):

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;
    }
}

这是正在发生的事情:

  1. 我启动脚本并正确获取进程(例如 Parentpid:2、childpid:3)
  2. 然后我向父级发送一个 SIGHUP 信号,它会正确地杀死和 启动一个新的子进程(例如 Parentpid: 2, childpid:4)
  3. 然后我向父级发送第二个 SIGHUP 信号,它会正确尝试并添加一个新的子进程,但它拒绝终止第二个子进程。 (例如 Parentpid:2、undyingchildpid:4、newchildpid:5)

让我知道这是否需要更多细节/没有意义。我不明白为什么第一次它会正确地杀死孩子,但第二次却没有。

更奇怪的部分是,当我更改它以更改我的重启处理程序以使其不断尝试使用 SIGINT 杀死孩子时,它每次都会失败,但是当我向它发送 SIGKILL 命令时,它会杀死孩子进程:

if($time_passed > 60){
    posix_kill($pid, SIGKILL);
}

我需要孩子能够被 SIGINT 杀死才能正确处理它。我不想只是 SIGKILL 它。是否有任何理由说明为什么第二次 SIGINT 不起作用,但 SIGKILL 会起作用?

【问题讨论】:

    标签: php fork subprocess kill-process pcntl


    【解决方案1】:

    首先,您不需要分叉。您的代码在孩子内部执行 exec,您基本上可以在没有分叉的情况下运行 exec,操作系统将在孩子的时候生成您的命令。如果要使用fork,只需include子文件中的文件而不是执行。

    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);
        }
    }
    

    另外,在使用 fork 时,您需要为孩子们​​waitpid。因此,在您的代码中,您需要插入类似的内容:

    //somewhere in a loop : 
    $pidOfExittedChild = pcntl_waitpid (-1, $status, WNOHANG);
    if ($pidOfExittedChild) {
        //a child has exitted, check its $status and do something
    }
    

    查看更多信息: http://php.net/manual/en/function.pcntl-waitpid.php

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多