至少发生在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。
为什么会出现这个问题,仍然是个谜,但我希望有人能够准确解释幕后到底发生了什么。