直接贴代码

phperv6

1、pcntl_signal_dispatch(); 能不能拿到while外面来,这就是一个信号调用函数,我看了源代码,好像里面也是一个循环,去检测信号队列,没有必要while两次
2、再者为什么要调用两次,我去掉了一个,wm也能跑起来

 protected static function monitorWorkers()
    {
        self::$_status = self::STATUS_RUNNING;
        while(1)
        {
            // 如果有信号到来,尝试触发信号处理函数
            pcntl_signal_dispatch();  
            // 挂起进程,直到有子进程退出或者被信号打断
            $status = 0;
            $pid = pcntl_wait($status, WUNTRACED);
            // 如果有信号到来,尝试触发信号处理函数
            pcntl_signal_dispatch();
            // 有子进程退出
            if($pid > 0)
            {
                // 查找是哪个进程组的,然后再启动新的进程补上
                foreach(self::$_pidMap as $worker_id => $worker_pid_array)
                {
                    if(isset($worker_pid_array))

3、主进程和子进程的信号处理,有什么不同,我感觉都是安装信号处理函数,不能公用么

 protected static function installSignal()
    {
        // stop
        pcntl_signal(SIGINT,  array('\Workerman\Worker', 'signalHandler'), false);
        // reload
        pcntl_signal(SIGUSR1, array('\Workerman\Worker', 'signalHandler'), false);
        // status
        pcntl_signal(SIGUSR2, array('\Workerman\Worker', 'signalHandler'), false);
        // ignore
        pcntl_signal(SIGPIPE, SIG_IGN, false);
    }

    /**
     * 为子进程重新安装信号处理函数,使用全局事件轮询监听信号
     * @return void
     */
    protected static function reinstallSignal()
    {
        // uninstall stop signal handler
        pcntl_signal(SIGINT,  SIG_IGN, false);
        // uninstall reload signal handler
        pcntl_signal(SIGUSR1, SIG_IGN, false);
        // uninstall  status signal handler
        pcntl_signal(SIGUSR2, SIG_IGN, false);
        // reinstall stop signal handler
        self::$globalEvent->add(SIGINT, EventInterface::EV_SIGNAL, array('\Workerman\Worker', 'signalHandler'));
        //  uninstall  reload signal handler
        self::$globalEvent->add(SIGUSR1, EventInterface::EV_SIGNAL,array('\Workerman\Worker', 'signalHandler'));
        // uninstall  status signal handler
        self::$globalEvent->add(SIGUSR2, EventInterface::EV_SIGNAL, array('\Workerman\Worker', 'signalHandler'));
    }
3168 1 0
1个回答

walkor

pcntl_signal_dispatch是检查当前进程是否收到信号,如果收到就执行信号处理函数(如果有的话)

1、这是主进程中的代码。pcntl_signal_dispatch不能拿到while外面来,拿到外面那么整个主进程生命周期就检查了一次信号,后面再有信号到来时就无法检查信号并响应,这个问题显而易见。
关于你说的while两次,即使pcntl_signal_dispatch的实现源码中是while循环,也是有退出条件的,不然pcntl_signal_dispatch就永远无法返回,有点服务器编程经验的都不会想永远阻塞在信号检查函数上不返回。

2、为什么while中调用pcntl_signal_dispatch两次。举个例子,一个工人(进程)在睡觉(pcntl_wait),被叫醒说有任务来了(有信号来了),工人开始处理任务包括检查信号(pcntl_signal_dispatch)以及fork进程(有需要的话),执行任务的过程中可能会有新的信号过来,这时工人是不知道的,所以在处理完任务后再次入睡(pcntl_wait)之前,工人需要再次检查(pcntl_signal_dispatch)是否又有新的任务出现。

另外主进程是阻塞在pcntl_wait上的,如果没有信号打断,那么将一直睡眠,不会有任何性能消耗。
也就是只有运行status、reload、restart等命令时才后执行到pcntl_signal_dispatch

3、子进程一般是使用libevent作为事件轮询库,信号处理需要重新注册到libevent中,所以需要把之前信号注册删掉

  • 暂无评论
年代过于久远,无法发表回答
🔝