至少發生在GNU bash 版本 4.3.42 x86_64&&GNU bash 版本 4.3.11 x86_64
我使用sleep & wait $!
而不是簡單地透過訊號sleep
來中斷(如sleep
SIGUSR1)。但當wait
您執行以下命令時,bash-builtin 的行為似乎很奇怪。
1號航廈:
cat <(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)&
2 號航廈:
kill -10 /the pid of the subshell, printed by the previous command/
1號航廈:
^C (ctrl + C)
然後,我得到了 100% 消耗 CPU 的子 shell。
1號航廈:
pkill -P $(pgrep -P $$)
您知道為什麼會出現這種行為嗎?
注意cat <(/subshell/)
:不在後台時不會出現問題。
體驗此行為的另一種方式
1號航廈:
(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)&
2 號航廈:
kill -10 /the pid of the subshell, printed by the previous command/
1號航廈:
fg
^C (ctrl + C)
然後,得到一個冷凍的殼。
體驗這種行為的第三種方式
1號航廈:
(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)
2 號航廈:
kill -10 /the pid of the subshell, printed by the previous command/
1號航廈:
^C (ctrl + C)
然後,得到一個冷凍的殼。
答案1
觀察結果
ctrl+c
發送SIGINT
到終端 1 中的 fg-process- 因此,在終端 2 中執行與在終端 1 中
kill -2 <PID>
執行相同ctrl+c
- 執行上述兩點之一前
kill -10 <PID>
在終端機 2 中執行可以SIGINT
正確處理 - 正在做後
kill -10 <PID>
在終端 2 中執行(發送訊號SIGUSR1
)無法SIGINT
正確處理並導致有問題的行為 kill -2 <PID>
將端子 2 中的 (SIGINT
)替換為kill -15 <PID>
(SIGTERM
) 或kill -9 <PID>
(SIGKILL
) 始終會導致正確的訊號處理。kill -10 <PID>
在終端 2 中執行會中斷wait
內建函數,但不會離開循環,因為test
在訊號SIGUSR1
被捕獲並且循環繼續後立即 printet 。- 發送
SIGINT
會中斷執行循環並凍結 shell,或者它永遠不會中斷wait
並保持等待/凍結狀態。
結論
SIGINT
未正確處理或在手動陷印SIGUSR1
或任何其他使用者定義的陷印後被忽略。這意味著該進程仍然存在,這就是它消耗/加熱 CPU 或凍結 shell 的原因。從終端 2執行kill -15 <PID>
或kill -9 <PID>
會終止/終止進程,並讓您重新獲得對終端 1 的控制權並放鬆 CPU。
為什麼會出現這個問題,仍然是個謎,但我希望有人能準確地解釋幕後到底發生了什麼事。