У меня есть следующий тестовый php для выполнения процесса fork / spawn, где тест также пытается убить дочерний процесс (zombie) после завершения.
Я хотел бы иметь более эффективный процесс, когда любые дочерние процессы немедленно удаляются из таблицы процессов как можно скорее. Текущая попытка заполняет таблицу процессов и вызывает проблему выделения памяти, которая отключает систему. Приложение работает в системе Fedora / Centos.
Я бегу в распределение памяти err, когда это работает, и существует слишком много процессов, которые появляются, пока они не будут удалены.
Любые указатели были бы очень благодарны за это спасибо ..
$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"; }
update ::: удалось получить то, что я думаю, это решение …..
//--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; } }
в//--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; } }
.//--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; } }
не//--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; } }
Просто используйте pcntl_wait (). Нет необходимости видеть, завершился ли дочерний процесс, просто вызовите pcntl_wait () и заблокируйте, пока ребенок не будет извлечен.
Избегайте передачи WNOHANG, чтобы ваш родительский процесс сидел и ждал, пока ребенок закончит.
Вы можете заменить написанный вами код (начиная с строки 58 '$ q = true;' вашего примера) следующим образом:
$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);
Вилка в 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 } } ?>