少なくともGNU bash バージョン 4.3.42 x86_64&&GNU bash バージョン 4.3.11 x86_64
シグナルによる割り込みを取得するために、sleep & wait $!
単純な方法の代わりに(sleep
sleep
SIGUSR1wait
)。しかし、以下を実行すると、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+c
SIGINT
ターミナル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 が緩和されます。
なぜこの問題が発生するのかは未だに謎のままですが、舞台裏で実際に何が起こっているのかを誰かが正確に説明してくれることを願っています。