PHP 代码中 Fork 函数导致的 Bug 处理

这几天遇到一个诡异的问题,同样的代码在一台机器上执行能获得正确结果,但另外一台机器上执行就出错。两台机器的环境本身就是不同的,一个是 CentOS 5,一个是 CentOS 7,使用的 PHP 版本也是不同。深入去分析出错的代码,最终发现是出现在多进程处理部分,Fork 函数出现了问题,新旧系统在 Fork 函数时,父子进程运行的先后顺序是不同的(2.6.32 以前内核是子进程先运行,2.6.32及之后是父进程先运行,并且尝试修改 kernel.sched_child_runs_first 发现也无法改变顺序),在新的机器上会导致代码不能顺利执行下去,跟进去查看,在 Fork.php 中的 start 函数中,子进程在执行完代码后是需要退出的,在新的系统中这里退出就会导致代码无法执行下去,注释掉 exit 虽然能够正常运行,但子进程不退出会带来很多如资源不释放、重复执行等其他问题。最终经过测试,发现将 exit 用 posix_kill(posix_getpid(), SIGTERM)来替代能够正常运行下去且会释放资源,具体代码如下:

function start()
    {
        if (!$this->_ipc_is_ok) {
        	 die ('Fatal error, unable to create SHM segments for process communications');
	         }
	
        pcntl_signal(SIGCHLD, SIG_IGN);
// 	pcntl_signal(SIGALRM, SIG_IGN);
	
        $pid = pcntl_fork();
        if ($pid == 0) {
            // this is the child
            $this->_isChild = true;
            sleep(1);
    	    
            // install the signal handler
            pcntl_signal(SIGUSR1, array($this, "_sig_handler"));
/*	    pcntl_signal(SIGALRM, array($this, "_sig_handler")); 
	    pcntl_alarm(1);                    	*/
	    
            // if requested, change process identity
            if ($this->_guid != 0)
                posix_setgid($this->_guid);
            if ($this->_puid != 0)
                posix_setuid($this->_puid);
	    $this->setVariable('_has_finished', false);		
       	    
	    if(func_num_args() > 0) {
	    	$args = func_get_args();
                call_user_func_array(array($this, 'run'), $args);
	    } else {
                $this->run();
	    }
	    $this->setVariable('_has_finished', true);	    
            // Added 21/Oct/2003: destroy the child after run() execution
            // needed to avoid unuseful child processes after execution
            // exit(0);
            posix_kill(posix_getpid(), SIGTERM); // replace exit
        } else {
            // this is the parent
            $this->_isChild = false;
            $this->_running = true;
            $this->_pid = $pid;
        }
    }

 

参考:
fork()父子进程运行先后顺序

发表评论

电子邮件地址不会被公开。 必填项已用*标注