等待 bash-builtin 将 CPU 烧毁至 100%

等待 bash-builtin 将 CPU 烧毁至 100%

至少发生在GNU bash 版本 4.3.42 x86_64&&GNU bash 版本 4.3.11 x86_64

我使用sleep & wait $!而不是简单地通过信号sleep来中断(如sleepSIGUSR1)。但当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。

为什么会出现这个问题,仍然是个谜,但我希望有人能够准确解释幕后到底发生了什么。

相关内容