親プロセスはSIGINTを受け取った後に基本操作を実行しません。

親プロセスはSIGINTを受け取った後に基本操作を実行しません。

bashで+を使用してCtrlSIGINTに対して2つのテストを実行しました。C

テスト1

親スクリプトとサブスクリプトの両方でハンドラを設定しますtrap

# !/bin/bash
# Parent.sh
trap 'echo "I handled the SIGINT in Parent.sh and expect the script going ahead."' SIGINT
echo 1.1
./Child.sh
echo 1.2
# !/bin/bash
# Child.sh
trap 'echo "I handled the SIGINT in Child.sh and expect the script going ahead."' SIGINT
echo 2.1
sleep 1000000000
echo 2.2
/tmp:$ ./Parent.sh
1.1
2.1
^CI handled the SIGINT in Child.sh and expect the script going ahead.
2.2
I handled the SIGINT in Parent.sh and expect the script going ahead.
1.2

出力は私が予想したものとほぼ同じです。

テスト2

サブスクリプトのみ設定ハンドラを渡しますtrap

# !/bin/bash
# Parent.sh
# trap 'echo "I expect I will be terminated immediately after Child.sh died."' SIGINT
echo 1.1
./Child.sh
echo "sleep started"
sleep 5
echo "sleep finished"
echo 1.2
# !/bin/bash
# Child.sh
trap 'echo "I handled the SIGINT in Child.sh and expect the script going ahead."' SIGINT
echo 2.1
sleep 1000000000
echo 2.2
/tmp:$ ./Parent.sh
1.1
2.1
^CI handled the SIGINT in Child.sh and expect the script going ahead.
2.2
sleep started
sleep finished
1.2

私はParent.shこれが死後直ちに終了しなければならないと予想しました(SIGINTの基本措置として)Child.sh

しかし、SIGINTを受けたようですがParent.sh無視します。

なぜですか?

答え1

このようなことが起こる理由は「待って協力していきましょう」(WCE)bash実装。

bashが子SIGINTプロセスを待っている間にシグナルを受信すると、そのシグナルによって子プロセスが終了した場合にのみ(子プロセスが終了するのではなく)、自らが終了します。親WIF*プロセスは、子プロセスの終了状態を介して、未処理の信号によって終了したか終了したかを確認できます。wait(2)マンページ。

より簡単な例:

bash -c 'sh -c "trap exit INT; read p"; echo DONE'
<ctrl-C>
DONE

そしてdashWCEを実装しないシェル:

dash -c 'sh -c "trap exit INT; read p"; echo DONE'
<ctrl-C>
<no DONE, parent script was killed outright>

似たようなものを見てくださいQ&A、しかも一緒に集める解決策としてこれを提案します。

関連情報