2012-03-12 20 views
8

Lemme首先給出我有的代碼的基本說明。我開始了與主父進程(注意:我不顯示爲簡單起見,所有功能讓我知道,如果你需要我在任何時候展開):隨後pcntl_signal信號不開始處理程序

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. 然後我發送消光nt第二個SIGHUP信號,它正確地嘗試並添加一個新的子進程,但它拒絕殺死第二個childpid。 (例如,Parentpid:2,undyingchildpid:4,newchildpid:5)

讓我知道是否需要更多細節/沒有意義。我無法弄清楚爲什麼第一次它會正確地殺死孩子,但第二次沒有。這個WEIRDER的部分是當我改變它以便我重新啓動處理程序,以便它不斷嘗試用SIGINT來殺死子項時,它每次都會失敗,但是當我發送一個SIGKILL命令時,它會殺死子進程:

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

我需要孩子能夠被SIGINT殺死才能正確處理它。我不想只是SIGKILL它。有沒有什麼理由說明爲什麼第二次使用SIGINT將不起作用,但SIGKILL會如何?

回答

1

首先,你不需要分叉。你的代碼在子內部執行一個exec,你可以基本上只運行exec而不是分叉,並且操作系統會在孩子時候產生你的命令。如果你想使用fork,只需要include這個文件在小孩而不是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); 
    } 
} 

此外,當使用分叉時,您需要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