Linux
程序在接收到未擷取的 SIGINT 後繼續執行(來自終端的 Ctrl-C)
我試圖
Ctrl-C
從 Centos7 的終端中斷一些正在執行的程序;有些會,有些不會。有問題的程序之一(Process-A)是一個沒有什麼花哨的 GNU makefile。只是通常的單文件製作系統。另一個(Process-B)是一個監聽 TCP 套接字的 C 應用程序。
以下是我在執行(並嘗試終止)其中一些有問題的程序時的觀察結果:
- Process-A 不會隨著
Ctrl-C
. 當盯著 strace -f 並Ctrl-C
按下時,strace 從子程序中分離並且strace 退出但 Process-A 繼續沒有 strace 日誌(這很奇怪)。- Process-B 不會隨著
Ctrl-C
. 當以 開頭時strace -f
,擷取 SIGINT 並按預期終止。- Process-B 不會隨著
Ctrl-C
. 當被抑製到後台並在外部發送 SIGINT 時(kill -s SIGINT PID
)仍然會丟棄它,而 SIGTERM 會殺死它。額外細節:
- 通過測試程序,我驗證了我的終端正在向程序發送 SIGINT(測試程序確實退出)。
- 在這兩個過程中,我都手動擷取任何信號。
- 嘗試使用多個終端應用程序來觀察相同的行為。
需要弄清楚這些信號是如何級聯的以及我在這裡缺少什麼。如何調試此類問題?
更新1:
我跑
grep 'search_string'
讓 grep 等待輸入STDIN
。現在我無法用Ctrl-C
. 開始懷疑它是否是特定於環境的問題。更新2:
經過一些工作,發現如下採購 RVM 腳本會導致此問題。
if [ -f ~/.rvm/scripts/rvm ]; then source ~/.rvm/scripts/rvm export PATH="$PATH:$HOME/.rvm/bin" fi
Process-A 不會因 Ctrl-C 而死,但 strace 會死(這很奇怪)
這一點也不奇怪,
strace
不是在處理信號,而是 Process-A 是。產生的信號control+c
被發送到前台程序組中的所有程序(除非終端處於其他模式),對於下面的測試案例,包括strace
和perl
。strace
退出,但忽略信號的過程會繼續執行,直到被其他方式殺死。% strace perl -E '$SIG{INT}="IGNORE";while(1){say $$;sleep 1}' ... % 9520 9520 9520 kill9520 9520 %
我執行 grep ‘search_string’ 讓 grep 等待 STDIN 中的輸入。現在我無法用 Ctrl-C 關閉它。
這確實指出了 shell 配置問題。
grep
可能已經從父程序繼承了信號處理程序,在這種情況下將是您的 shell。我有一個blocksig
說明這種情況的腳本:% grep asdf ^C % blocksig grep asdf ^C^C^C^C^C^]^\zsh: quit blocksig grep asdf %
但是,在您的情況下,它是您的外殼,而不是
blocksig
父程序。當您切換到其他 shell 或在不讀取典型rc
文件的情況下啟動 shell 時會發生什麼?您的 shell 配置中是否有任何trap
設置或自定義作業或作業監控配置?