国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

關(guān)于執(zhí)行兩次pcntl_signal_dispatch的問題,煩請解惑

andyc

我看pcntl源碼中php_pcntl_pending_signal先初始化為32個,丟失信號的場景就是信號隊列滿了吧,代碼如下:
psig = PCNTL_G(spares);
if (!psig) {
/ oops, too many signals for us to track, so we'll forget about this one /
return;
}

如果隊列沒滿的話是可以繼續(xù)處理的,如果滿了,來的信號都丟了,第二次的pcntl_signal_dispatch 是預(yù)防那些場景那?相關(guān)php代碼如圖片所示

3843 2 1
2個回答

walkor 打賞

pcntl_signal_dispatch()是處理已經(jīng)收到的信號。

假設(shè)只有一個pcntl_signal_dispatch(),
截圖里代碼簡化成如下

while (1){
    pcntl_signal_dispatch(); // 位置1
    $pid= pcntl_wait();        // 位置2
}

正常情況下,進(jìn)程是阻塞在位置2。
當(dāng)信號到來時,pcntl_wait()返回,代碼繼續(xù)執(zhí)行,就執(zhí)行到了位置1。
執(zhí)行1程中,這時候有新的信號到來,新的信號放入信號隊列不做處理(因為需要再次調(diào)用pcntl_signal_dispatch()才能被處理)。
執(zhí)行完1后代碼繼續(xù)執(zhí)行2,然后一直阻塞在2的位置,新來的信號沒有被處理(這里其實意思是沒被處理,信號其實沒丟)。

所以在workerman里又調(diào)用了一次pcntl_signal_dispatch(),這樣能夠盡量避免漏掉信號。

以下是丟失信號的一個demo,你可以自己測試下。
test.php

<?php
echo "pid=".posix_getpid()."\n";
pcntl_signal(SIGUSR1, function(){
    echo "GET SIGNAL\n";
    posix_kill(posix_getpid(), SIGUSR1); // 這里模擬在處理信號的過程中收到新的信號
}, false);

while (1) {
    pcntl_signal_dispatch();
    sleep(10000);
    //pcntl_signal_dispatch(); 
}

運行 php test.php,然后在另外一個終端上給這個進(jìn)程發(fā)送信號 kill -SIGUSR1 pid,如果只有一個 pcntl_signal_dispatch();,你會看到只打印一個 GET SIGNAL。但是實際上代碼執(zhí)行過程中一共收到了2個信號。
有一個信號看起來丟失了。

  • andyc 2020-09-28

    嗯,感謝,另外,如果系統(tǒng)調(diào)用有超時設(shè)置的話(例如select)并且在退出系統(tǒng)調(diào)用的時候不會退出while循環(huán)的情況下,其實一次也夠了

  • walkor 2020-09-28

    必須2個,靠超時觸發(fā)的話有延遲。

  • a2005826 2021-04-06

    @1:老大問下,同時過來2個信號,為啥sleep 10000下面的pcntl_signal_dispatch也能運行,sleep對它不起作用嗎?

  • walkor 2021-04-07

    信號會打斷sleep

andyc

@walkor:就像你說的兩個也是盡量避免漏掉,如果在執(zhí)行第二個的時候又來了個信號,但是執(zhí)行完之后會退出循環(huán),一樣會有信號漏掉,當(dāng)然這是極端的情況。我說的那種情況就像Events/select中的loop一樣(當(dāng)然也有可能漏掉),就像如下代碼:
截圖

  • walkor 2020-09-29

    對,都是盡量避免漏掉。loop這里考慮性能問題,只使用了一個pcntl_signal_dispatch();

年代過于久遠(yuǎn),無法發(fā)表回答
??