Bash

如果 Bash 目前正在執行的子程序處理它,為什麼 Bash 會忽略 SIGINT?

  • July 21, 2021

如果我用以下命令中斷它,則以下 Bash 循環將停止^C

(while true; do sleep 5; done)

但是,以下內容不會:

(while true; do aplay test.wav; done)

據我所知,不同之處在於aplaycatch 和 handle SIGINT,而sleep沒有。

為什麼是這樣?POSIX 是否在某處指定了這種行為(我注意到 Dash 做了同樣的事情),如果是這樣,為什麼?我不太明白為什麼這種行為是可取的。事實上,Bash 怎麼能分辨出來呢?我必須承認我不知道有任何機制(至少除了ptrace/proc/黑客之外)一個程序可以告訴另一個程序如何處理信號。

另外,有什麼辦法可以抵消嗎?我注意到trap 'exit 0' SIGINT循環之前甚至沒有幫助。

編輯:在子外殼中執行循環很重要,因為否則父外殼不會收到SIGINT。)

這個問題在這裡得到了很好的解釋,因為WCE 等待和合作退出,我鼓勵你閱讀它。基本上,所有前台程序(即shell 和程序、睡眠或播放)都會收到您的信號。如果程序未處理該信號,則程序以返回碼 130 退出。shell 等待子程序結束,並看到這一點,以及它也收到信號的事實,所以退出。

當程序擷取信號時,它通常只是以程式碼 1 退出(與 aplay 一樣)。當 shell 等待子程序時,它發現它沒有因為信號而結束,因此必須假設信號是程序工作的正常方面,所以 shell 正常執行。

對於您的範例,處理 aplay 的最佳方法是檢查其返回碼是否為非零並停止:

(while aplay test.wav; do :; done)

上面提到的文章繼續解釋了一個行為良好的程序想要擷取 sigint 進行一些清理,然後應該禁用它的處理程序,並重新殺死自己以獲得正確的退出標誌設置。

引用自:https://unix.stackexchange.com/questions/287044