2011-02-17 1 views
0

je le php test suivant pour faire un processus fourchette/spawn, où le test tente également de tuer le processus fils (zombie) AFTER est battant ..php question bifurquer

Je voudrais avoir un plus processus efficace, où tous les processus enfants sont immédiatement supprimés de la table de processus dès que possible. La tentative en cours remplit la table de processus et provoque un problème d'allocation de mémoire qui arrête le système. L'application fonctionne sur un système Fedora/Centos.

Je suis dans une erreur d'allocation de mémoire lorsque cela s'exécute, et il y a trop de processus qui sont engendrés, avant d'être supprimés.

Les pointeurs seraient grandement appréciés sur ce merci ..

$fname="ef_deptData.txt"; 

$t=0; 
$pids = array(); 
$pids1[] = array(); 


$fh=fopen($fname,"r"); 
$p=0; 
while(!feof($fh)) 
{ 
    print " inside course pppppppppppppppppppppp \n"; 
    //--go ahead and parse the line of input from the file 
    //--(if it exists) 

    $buf = fgets($fh); 

    $buf=trim($buf); 
    if($buf) 
    { 
     $data1=explode("&&",$buf); 
     $stateVal=trim($data1[0]); 
     $collegeVal=trim($data1[1]); 
     $campusVal=trim($data1[2]); 

     $pid = pcntl_fork(); 

     //process the spawned child procs 
     if($pid) 
     { 
      $pids[$p]=$pid; 
      $p=$p+1; 
     } 
     else 
     { 
      $app="ef_course.py"; 

      $args[0]='"'.$stateVal.'"'; 
      $args[1]='"'.$collegeVal.'"'; 
      $args[2]='"'.$campusVal.'"'; 

      pcntl_exec($app, $args); 
     } 
    } 
    $t=$t+1; 
    if($t==40) 
    { 
     sleep(5); 
     $t=0; 
    } 
} 


    // --this section is a kludge to see if the child process is complete 
    // --prior to deleting the spwaned child process (should be a better way) 
$q=true; 
    while($q) 
    { 
      $a="ps -aux | grep ef_course | grep -v grep | awk '{print $8}'"; 
      $a=`$a`; 
      $t=explode("\n",$a); 
      $t=array_slice($t,1,-1); 
      print_r($t); 
      sleep(5); 
      $y=0; 

      for($i=0;$i<count($t);$i++) 
      { 
        if((strcmp($t[$i],"Z+")!=0)&&(strcmp($t[$i],"Z")!=0)) 
        { 
          $y=1; 
          print "ddd \n"; 
        } 
      } 

      if($y==0) 
    { 
     //--try to go ahead and kill the zombie processes 
     $w="pgrep ef_course"; 
     $r=`$w`; 
     if($r!="") 
     { 
      //foreach($pids as $p){ posix_kill($p,SIGHUP); } 
      //foreach($pids as $p){ posix_kill($p,SIGINT); } 
      foreach($pids as $p){ posix_kill($p,SIGTERM); } 

      $dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG); 
      while($dead_and_gone > 0){ 
       // Remove the gone pid from the array 
       unset($pids[array_search($dead_and_gone,$pids)]); 

       // Look for another one 
       $dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG); 
      } 
      print_r($pids); 
     } 
     else 
      $q=false; 
    } 
    sleep(10); 
    print "waiting for ef_course.py to complete \n"; 
} 

mise à jour ::: a réussi à obtenir ce que je pense est une solution .....

//--start the process to get the store urls.. 
$fname="ef_programData.txt"; 

$t=0; 
$pids = array(); 
$pids1[] = array(); 


    $fh=fopen($fname,"r"); 
    $p=0; 
    while(!feof($fh)) 
    { 
      print " inside program pppppppppppppppppppppp \n"; 
     //--go ahead and parse the line of input from the file 
     //--(if it exists) 

      $tmp=array(); 
      $buf = fgets($fh); 

      $buf=trim($buf); 
      if($buf) 
      { 
        $data1=explode("&&",$buf); 

        $pid = pcntl_fork(); 

        //process the spawned child procs 
        if($pid) 
        { 
          $pids[]=$pid; 
        } 
        else 
        { 
          $args=array(); 
          $app="foo.py"; 

          $args[0]='"'.$stateVal.'"'; 

          pcntl_exec($app, $args); 
        } 

        while(pcntl_wait($status, WNOHANG) > 0) { 
         usleep(500); 
        } 

        while(list($key, $val) = each($pids)) { 
        if(!posix_kill($val, 0)) { // This detects if the child is still running or not 
          unset($pids[$key]); 
        } 
        } 
        $pids = array_values($pids); // Reindex the array 

      } 
      $t=$t+1; 
      if($t==40) 
      { 
        sleep(5); 
        $t=0; 
      } 
    } 

Répondre

2

Il suffit d'utiliser pcntl_wait(). Il n'est pas nécessaire de voir si le processus fils a fini, appelez simplement pcntl_wait() et bloquez jusqu'à ce que l'enfant soit récolté.

Évitez de transmettre WNOHANG de sorte que votre processus parent reste en place et attende la fin de l'enfant.

Vous pouvez remplacer le code récolte que vous avez écrit (à partir de la ligne 58 '$ q = true;' de votre exemple) avec ceci:

$status = null; 

do { 
    // You can use $status with pcntl_wifexited(), pcntl_wifstopped(), 
    // pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig() and 
    // pcntl_wstopsig() if you need to. 

    $pid = pcntl_wait($status); 

} while ($pid > 0); 
1

Fourchette à foreach:

<? 
declare(ticks=1); 
pcntl_signal(SIGUSR1, create_function('$signo', 'sleep(1);while (($pid=pcntl_wait(@$status, WNOHANG))>0) {}'));//protect against zombie children 
foreach ($tasks as $v) 
     {if (($pid=pcntl_fork())===-1) 
      {//... 
      continue; 
      } 
     else if ($pid===0) 
       {ob_start();//prevent output to main process 
       register_shutdown_function(create_function('$pars', 'ob_end_clean();posix_kill(posix_getppid(), SIGUSR1);posix_kill(getmypid(), SIGKILL);'), array());//to kill self before exit();, or else the resource shared with parent will be closed 
       //... 
       exit();//avoid foreach loop in child process 
       } 
     } 
?>