1、pcntl_signal_dispatch(); 能不能拿到while外面來,這就是一個信號調(diào)用函數(shù),我看了源代碼,好像里面也是一個循環(huán),去檢測信號隊列,沒有必要while兩次
2、再者為什么要調(diào)用兩次,我去掉了一個,wm也能跑起來
protected static function monitorWorkers()
{
self::$_status = self::STATUS_RUNNING;
while(1)
{
// 如果有信號到來,嘗試觸發(fā)信號處理函數(shù)
pcntl_signal_dispatch();
// 掛起進程,直到有子進程退出或者被信號打斷
$status = 0;
$pid = pcntl_wait($status, WUNTRACED);
// 如果有信號到來,嘗試觸發(fā)信號處理函數(shù)
pcntl_signal_dispatch();
// 有子進程退出
if($pid > 0)
{
// 查找是哪個進程組的,然后再啟動新的進程補上
foreach(self::$_pidMap as $worker_id => $worker_pid_array)
{
if(isset($worker_pid_array))
3、主進程和子進程的信號處理,有什么不同,我感覺都是安裝信號處理函數(shù),不能公用么
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);
}
/**
* 為子進程重新安裝信號處理函數(shù),使用全局事件輪詢監(jiān)聽信號
* @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'));
}
pcntl_signal_dispatch是檢查當前進程是否收到信號,如果收到就執(zhí)行信號處理函數(shù)(如果有的話)
1、這是主進程中的代碼。pcntl_signal_dispatch不能拿到while外面來,拿到外面那么整個主進程生命周期就檢查了一次信號,后面再有信號到來時就無法檢查信號并響應,這個問題顯而易見。
關(guān)于你說的while兩次,即使pcntl_signal_dispatch的實現(xiàn)源碼中是while循環(huán),也是有退出條件的,不然pcntl_signal_dispatch就永遠無法返回,有點服務器編程經(jīng)驗的都不會想永遠阻塞在信號檢查函數(shù)上不返回。
2、為什么while中調(diào)用pcntl_signal_dispatch兩次。舉個例子,一個工人(進程)在睡覺(pcntl_wait),被叫醒說有任務來了(有信號來了),工人開始處理任務包括檢查信號(pcntl_signal_dispatch)以及fork進程(有需要的話),執(zhí)行任務的過程中可能會有新的信號過來,這時工人是不知道的,所以在處理完任務后再次入睡(pcntl_wait)之前,工人需要再次檢查(pcntl_signal_dispatch)是否又有新的任務出現(xiàn)。
另外主進程是阻塞在pcntl_wait上的,如果沒有信號打斷,那么將一直睡眠,不會有任何性能消耗。
也就是只有運行status、reload、restart等命令時才后執(zhí)行到pcntl_signal_dispatch
3、子進程一般是使用libevent作為事件輪詢庫,信號處理需要重新注冊到libevent中,所以需要把之前信號注冊刪掉