bash組み込みのCPU使用率を100%まで上げる

bash組み込みのCPU使用率を100%まで上げる

少なくともGNU bash バージョン 4.3.42 x86_64&&GNU bash バージョン 4.3.11 x86_64

シグナルによる割り込みを取得するために、sleep & wait $!単純な方法の代わりに(sleepsleepSIGUSR1wait)。しかし、以下を実行すると、bash 組み込みコマンドが奇妙な動作をするようです。

ターミナル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)

次に、CPU を 100 パーセント消費するサブシェルを取得します。

ターミナル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)

次に、冷凍シェルを入手します。


この行動を体験する3番目の方法

ターミナル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+cSIGINTターミナル1のfgプロセスに送信
  • したがって、ターミナル2で実行することはターミナル1でkill -2 <PID>ヒットすることと同じです。ctrl+c
  • 上記の2つのポイントのうち1つを実行する前にkill -10 <PID>ターミナル2で実行するとSIGINT正しく処理されます
  • しているターミナル2での実行kill -10 <PID>(シグナルの送信SIGUSR1)は正しく処理されずSIGINT、問題のある動作につながる
  • kill -2 <PID>端子2の( SIGINT)をkill -15 <PID>( SIGTERM)またはkill -9 <PID>( )に置き換えるとSIGKILL、常に正しい信号処理が行われます。
  • kill -10 <PID>ターミナル 2 で実行するとwait組み込み関数が中断されますが、test信号SIGUSR1がトラップされてループが継続するとすぐに printet が実行されるため、ループは終了しません。
  • 送信するとSIGINT実行ループが終了し、シェルがフリーズするか、または中断されずにwait待機/フリーズしたままになります。

結論

SIGINT正しく捕捉および処理されないか、手動でトラップした後SIGUSR1、または他のユーザー定義のトラップ後に無視されます。これはプロセスがまだ存在していることを意味し、これが CPU を消費/加熱したり、シェルをフリーズさせたりします。ターミナル 2 からkill -15 <PID>またはを実行するとkill -9 <PID>、プロセスが終了/強制終了され、ターミナル 1 の制御が戻り、CPU が緩和されます。

なぜこの問題が発生するのかは未だに謎のままですが、舞台裏で実際に何が起こっているのかを誰かが正確に説明してくれることを願っています。

関連情報