PHP fork limit childs in the task

妖精的绣舞 提交于 2021-02-04 13:48:13

问题


* SOLUTION IN THE ANSWER BELOW *

I got a problem with limiting childs in the multifork php script... Seems like last child never ends... I'm really tired and can't find the error, could You please help? It does not end most of times...

<?php
declare(ticks = 1);

$max=5;
$child=0;

function sig_handler($signo) {
    global $child;
    switch ($signo) {
        case SIGCHLD:
        $child -= 1;
        echo "[-]";
    }
}

pcntl_signal(SIGCHLD, "sig_handler");

$found = array(1,2,3,4,5,6,7,8,9,10,11,12);

echo "LETS GO!\n";

foreach($found as $item){

            while ($child >= $max) {
            sleep(1);
        }

        $child++;
        echo "[+]";
        $pid=pcntl_fork();

        if($pid){
        }else{ // CHILD
            sleep(rand(1,5));
            echo "[~]";
            exit(0);
        }

}

while($child != 0){
    echo "($child)";
    sleep(1);
}

echo "THE END.\n"

?>

Result most times is:

[+][+][+][+][+][~][-][+][~][-][+][~][-][+][~][-][+][~][-][+][~][-][+][~][~][~][-][+]    (5)[-](4)(4)[~][-](3)[~][-](2)(2)[~](2)[-](1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)(1)... etc etc ...

Seems like last child does not end at all or at least it doesnt trigger sig handler...

  • [+] <- just before forking - count: 12
  • [~] <- just before child exit - count: 12
  • [-] <- sig handler after child exit - count: 11

Help?

PS. The weird thing is that it sometimes does end.


回答1:


Ok found the solution:

function sig_handler($signo){
  global $child;
  switch ($signo) {
    case SIGCLD:
      while( ( $pid = pcntl_wait ( $signo, WNOHANG ) ) > 0 ){
        $signal = pcntl_wexitstatus ($signo);
        $child -= 1;
        echo "[-]";       
      }
    break;
  }
}

The problem was in the way of handling signals on UNIX systems. All sigs sent in similar time are being grouped to one. The function above fixes that problem. And not only that one... when child exits immediately, it doesn't segfault ("zend_mm_heap corrupted" error in some PHP configurations/versions) anymore. And it did in previous case.

PS. I should delete this question, but I will leave the solution for everyone experiencing similar problems as multithreading in PHP scripts is very useful for some tasks.



来源:https://stackoverflow.com/questions/17526509/php-fork-limit-childs-in-the-task

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!