예제 #1
0
 /**
  * 监控worker进程状态,退出重启
  * @param resource $channel
  * @param int $flag
  * @param int $pid 退出的进程id
  */
 public static function monitorWorkers($wait_pid = -1)
 {
     // 由于SIGCHLD信号可能重叠导致信号丢失,所以这里要循环获取所有退出的进程id
     while (($pid = pcntl_waitpid($wait_pid, $status, WUNTRACED | WNOHANG)) != 0) {
         // 如果是重启的进程,则继续重启进程
         if (isset(self::$workerToRestart[$pid]) && self::$serverStatus != self::STATUS_SHUTDOWN) {
             Telnet::sendToAllClient(".");
             unset(self::$workerToRestart[$pid]);
             self::restartWorkers();
         }
         // 出错
         if ($pid == -1) {
             // 没有子进程了,可能是出现Fatal Err 了
             if (pcntl_get_last_error() == 10) {
                 self::notice('Server has no workers now');
             }
             return -1;
         }
         // 查找子进程对应的woker_name
         $pid_workname_map = self::getPidWorkerNameMap();
         $worker_name = isset($pid_workname_map[$pid]) ? $pid_workname_map[$pid] : '';
         // 没找到worker_name说明出错了 哪里来的野孩子?
         if (empty($worker_name)) {
             self::notice("child exist but not found worker_name pid:{$pid}");
             break;
         }
         // 进程退出状态不是0,说明有问题了
         if ($status !== 0 && self::$serverStatus != self::STATUS_SHUTDOWN) {
             self::notice("worker exit status {$status} pid:{$pid} worker:{$worker_name}");
         }
         // 记录进程退出状态
         self::$serverStatusInfo['err_info'][$worker_name][$status] = isset(self::$serverStatusInfo['err_info'][$worker_name][$status]) ? self::$serverStatusInfo['err_info'][$worker_name][$status] + 1 : 1;
         // 清理这个进程的数据
         self::clearWorker($worker_name, $pid);
         // 如果服务是不是关闭中
         if (self::$serverStatus != self::STATUS_SHUTDOWN) {
             // 重新创建worker
             self::createWorkers();
             // 开发环境需要上报监控文件给FileMonitor
             if ($worker_name == 'FileMonitor') {
                 Reporter::reportIncludedFiles(self::$filesToInotify);
             }
         } else {
             $all_worker_pid = self::getPidWorkerNameMap();
             if (empty($all_worker_pid)) {
                 // 发送提示
                 self::notice("Server stoped");
                 // 关闭管理员socket
                 Telnet::close();
                 // 删除pid文件
                 @unlink(PID_FILE);
                 exit(0);
             }
         }
         //end if
     }
     //end while
 }