M89*_*M89 17 shell bash signals shell-script trap
至少在GNU bash 版本 4.3.42 x86_64 && GNU bash 版本 4.3.11 x86_64 上发生
我使用sleep & wait $!而不是简单的sleep来获得sleep信号的可中断性(如SIGUSR1)。但是wait当您运行以下命令时,bash-builtin 的行为似乎很奇怪。
cat <(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)&
Run Code Online (Sandbox Code Playgroud)
kill -10 /the pid of the subshell, printed by the previous command/
Run Code Online (Sandbox Code Playgroud)
^C (ctrl + C)
Run Code Online (Sandbox Code Playgroud)
然后,我得到了以 100% 消耗 CPU 的子外壳。
pkill -P $(pgrep -P $$)
Run Code Online (Sandbox Code Playgroud)
你知道为什么会发生这种行为吗?
注意:cat <(/subshell/)不在后台时不会出现问题。
(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)&
Run Code Online (Sandbox Code Playgroud)
kill -10 /the pid of the subshell, printed by the previous command/
Run Code Online (Sandbox Code Playgroud)
fg
^C (ctrl + C)
Run Code Online (Sandbox Code Playgroud)
然后,得到一个冷冻的壳。
(
trap 'echo SIGUSR1' SIGUSR1;
echo $BASHPID;
while :;do
sleep 1 &
wait $!;
echo test;
done
)
Run Code Online (Sandbox Code Playgroud)
kill -10 /the pid of the subshell, printed by the previous command/
Run Code Online (Sandbox Code Playgroud)
^C (ctrl + C)
Run Code Online (Sandbox Code Playgroud)
然后,得到一个冷冻的壳。
观察结果
ctrl+c发送SIGINT到终端 1 中的 fg-processkill -2 <PID>执行相同ctrl+ckill -10 <PID>SIGINTkill -10 <PID>SIGUSR1SIGINTkill -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。
为什么会出现这个问题,仍然是个谜,但我希望有人能够准确解释幕后到底发生了什么。