2012-03-12 14 views
8

Déjenme comenzar dando una descripción básica del código que tengo. Empiezo con un proceso padre principal. (Nota: No estoy mostrando todas las funciones para simplificar Quiero saber si me necesita ampliar en cualquier momento):Señales posteriores de pcntl_signal que no inician el controlador

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

Aquí está lo que está sucediendo:

  1. comienzo mi guión y me sale correctamente los procesos (por ejemplo Parentpid: 2, childpid: 3)
  2. I a continuación, enviar a los padres una señal SIGHUP y mata correctamente y inicia un nuevo proceso hijo (por ejemplo Parentpid: 2 , childpid: 4)
  3. Luego envío el pare nt una segunda señal SIGHUP e intenta y agrega correctamente un nuevo proceso hijo, pero se niega a matar el 2nd childpid. (por ejemplo, Parentpid: 2, undyingchildpid: 4, newchildpid: 5)

Dígame si necesita más información/no tiene sentido. No puedo entender por qué la primera vez mataría a los niños, pero la segunda vez no.

La parte uniforme WEIRDER es que cuando lo cambio para que cambie mi controlador de reinicio para que siga intentando matar al niño con un SIGINT, falla cada vez, pero cuando le envío un comando SIGKILL mata al proceso hijo:

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

Necesito que el niño pueda ser asesinado por SIGINT para manejarlo correctamente. No quiero simplemente SIGKILL. ¿Hay alguna razón por la cual la segunda vez en SIGINT no funcionaría, pero SIGKILL lo haría?

Respuesta

1

Antes que nada, no necesita tenedor. Su código hace un ejecutivo dentro del niño, básicamente podría simplemente ejecutar el ejecutor sin bifurcación, y el sistema operativo generará su comando como un niño. Si desea utilizar fork, simplemente include el archivo en el hijo en lugar de la ejecució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); 
    } 
} 

Además, al utilizar tenedor, es necesario waitpid para los niños. Por lo tanto, en el código tiene que insertar algo como:

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

Comprobar más en: http://php.net/manual/en/function.pcntl-waitpid.php

Cuestiones relacionadas