Linux

程序在接收到未擷取的 SIGINT 後繼續執行(來自終端的 Ctrl-C)

  • October 26, 2018

我試圖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 會殺死它。

額外細節:

  1. 通過測試程序,我驗證了我的終端正在向程序發送 SIGINT(測試程序確實退出)。
  2. 在這兩個過程中,我都手動擷取任何信號。
  3. 嘗試使用多個終端應用程序來觀察相同的行為。

需要弄清楚這些信號是如何級聯的以及我在這裡缺少什麼。如何調試此類問題?

更新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被發送到前台程序組中的所有程序(除非終端處於其他模式),對於下面的測試案例,包括straceperlstrace退出,但忽略信號的過程會繼續執行,直到被其他方式殺死。

% 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設置或自定義作業或作業監控配置?

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