2012-03-12 14 views
8

Lemme, sahip olduğum kodun temel bir tanımını vererek başlıyor. Ben bir ana ana süreç ile başlamak (NOT:. Ben basitlik için tüm fonksiyonları gösteren değilim Eğer herhangi bir noktada genişletmek için bana ihtiyacın olursa haber ver):Takip eden pcntl_signal sinyalleri işleyiciyi başlatmıyor

İşte
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; 
    } 
} 

ne oluyor edilir:

  1. benim senaryoyu başlatmak ve düzgün süreçleri (örneğin Parentpid: 2, childpid: 3) almak
  2. sonra ebeveyni bir SIGHUP sinyali göndermek ve düzgün öldürür ve yeni çocuk sürecini başlatır (örneğin Parentpid: 2 childPid: 4)
  3. Daha sonra pare gönderirim 2. SIGHUP sinyali yoktur ve düzgün bir şekilde çalışır ve yeni bir çocuk süreci ekler, ancak 2. çocuk hastalığını öldürmeyi reddeder. (örneğin, Parentpid: 2, undyingchildpid: 4, newchildpid: 5)

Bunun daha fazla ayrıntıya ihtiyaç duyup duymadığını/mantıklı olmadığını bilin. Çocukları ilk kez neden doğru bir şekilde öldüreceğini anlayamıyorum, ama ikinci kez değil.

WEIRDER'in bir kısmı bile, değiştirdiğimde, yeniden başlatma işleyicimi değiştirerek, SIGINT ile çocuğu öldürmeyi denemeye devam ettiğimde, her seferinde başarısız oluyor, ancak SIGKILL komutunu gönderdiğimde Çocuk işlemi: Düzgün işlemek için SIGINT tarafından öldürülmesi gereken çocuğa ihtiyacım var. Sadece SIGKILL istemiyorum. SIGINT'in 2'nci saatinin neden işe yaramayacağı konusunda bir neden var mı, SIGKILL yapacak?

cevap

1

Her şeyden önce çatallamanız gerekmez. Kodunuz çocuğunuzun içinde bir yürütme gerçekleştirir, temel olarak sadece formadan kaçmadan çalıştırırsınız ve işletim sisteminiz çocuk olarak komutunuzu doğurur. Çatal kullanmak istiyorsanız, sadece include dosyasını dosya yerine yürütmek yerine. çatal kullanırken

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

Ayrıca, çocuklar için waitpid gerekir. En

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

kontrol daha: http://php.net/manual/en/function.pcntl-waitpid.php

Yani, kodunuzda bir şey gibi eklemek gerekir