2012-03-12 29 views
8

Hãy bắt đầu bằng cách đưa ra một mô tả cơ bản về mã tôi có. Tôi bắt đầu với một quá trình cha mẹ chính (LƯU Ý:. Tôi không hiển thị tất cả các chức năng để đơn giản Hãy cho tôi biết nếu bạn cần tôi để mở rộng bất cứ lúc nào):Các tín hiệu pcntl_signal tiếp theo không khởi động trình xử lý

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

Dưới đây là những gì đang xảy ra:

  1. tôi bắt đầu kịch bản của tôi và tôi đúng được các quá trình (ví dụ Parentpid: 2, childpid: 3)
  2. sau đó tôi gửi cho phụ huynh một tín hiệu SIGHUP và nó đúng cách giết chết và bắt đầu một quá trình con mới (ví dụ Parentpid: 2 , childpid: 4)
  3. Sau đó tôi gửi ảnh chụp nt một tín hiệu SIGHUP thứ hai và nó đúng cách cố gắng và thêm một quá trình con mới, nhưng nó từ chối giết đứa trẻ thứ hai. (ví dụ: Parentpid: 2, undyingchildpid: 4, newchildpid: 5)

Hãy cho biết nếu cần thêm chi tiết/không có ý nghĩa. Tôi không thể tìm ra lý do tại sao lần đầu tiên nó giết chết bọn trẻ, nhưng lần thứ hai thì không.

Phần WEIRDER thậm chí là khi tôi thay đổi nó để tôi thay đổi trình xử lý khởi động lại để nó cố gắng giết con bằng SIGINT, nó không thành công mỗi lần, nhưng khi tôi gửi lệnh SIGKILL, nó sẽ giết chết quy trình con:

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

Tôi cần trẻ có thể bị SIGINT giết để xử lý đúng cách. Tôi không muốn chỉ SIGKILL nó. Có lý do gì để giải thích tại sao lần thứ hai xung quanh SIGINT không hoạt động, nhưng SIGKILL sẽ?

Trả lời

1

Trước hết, bạn không cần phải ngã ba. Mã của bạn thực hiện một hành động bên trong con, về cơ bản bạn có thể chạy lệnh exec whithout forking và hệ điều hành sẽ sinh ra lệnh của bạn như một đứa trẻ. Nếu bạn muốn sử dụng ngã ba, chỉ cần include tệp ở trẻ thay vì thực hiện.

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

Ngoài ra, khi sử dụng nĩa, bạn cần phải waitpid cho trẻ em. Vì vậy, trong mã của bạn, bạn cần phải chèn cái gì đó như:

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

Kiểm tra chi tiết tại: http://php.net/manual/en/function.pcntl-waitpid.php

Các vấn đề liên quan