子プロセスを異常終了させる信号が原因でbashは終了しません。

子プロセスを異常終了させる信号が原因でbashは終了しません。

私は何が間違っているのか、そしてその理由が何であるかを理解しようとして本当に頑張っています。

launch.sh起動スクリプトがありますprocess.sh

start.sh

#!/bin/bash
while true; do 
./process.sh 
done

process.sh

#!/bin/bash
function signalHandler() {
    for i in {1..2}; do
        sleep 0.1s
        echo "process.sh: cleanup $i"
    done
    exit 130
}

trap "signalHandler" "SIGINT"

while true; do 
sleep 1s
done

私が走るとき

./launch.sh &

その後、使用

kill -s SIGINT -$!    

最後のコマンド(launch.sh)のPIDを取得する$!マイナス記号は、すべての子プロセスにシグナルを送信して続行launch.shします。なぜ?


次のような行動を楽しみにしています(このブログによると信号とスラム):

バックグラウンドでスクリプトを実行しているシェルAがlaunch.shハングし、Bashがprocess.sh完了するのを待ちます。process.shのシグナルハンドラが例外return(出口130)を発生させるため、process.shシェルAを終了する必要があります。なぜできないの?

子プロセスの状態がこのシグナルのために異常終了したことを示す場合、シェルはクリーンアップし、対応するシグナルハンドラを削除し、再びシャットダウンしてオペレーティングシステムのデフォルト動作(異常終了)をトリガーします。または、トラップ設定に従ってスクリプトのシグナルハンドラを実行し、続行します。

答え1

まず、exit 130異常終了したかどうかです。正常に終了し、終了状態は130です。わかるようにman 3 wait(POSIX):

   If  the  information  pointed  to  by  stat_loc was stored by a call to
   waitpid()  that  specified  the  WUNTRACED     and  WCONTINUED   flags,
   exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
   WIFSTOPPED(*stat_loc),  and WIFCONTINUED(*stat_loc)  shall evaluate  to
   a non-zero value.

WIFEXITED正常終了を確認し、WIFSIGNALLED捕捉されていない信号により終了する。これらは相互に排他的であるため、anexit 130は正常です。

SIGINTがプロセスを終了すると、bashはSIGINTが終了を検出し、プロセスの外部でこれを130に設定するため、終了ステータスは130です。bashが$を設定するのはなぜですか? (終了ステータス) が Ctrl-C または Ctrl-Z ではゼロではないのですか?

次に、SIGINTを処理してから終了するプロセスは、SIGINTを使用して自分で終了する必要があります。 Gregのwiki(シェルのための素晴らしい資料)これに関する注意:

EXITトラップを使用する代わりにSIGINTのハンドラを設定することを選択した場合、SIGINTに応答して終了するプロセスSIGINTで自殺発信者に問題を引き起こさないように、単に終了するだけではありません。したがって:

trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT

さて、次のように変更した場合exit 130

trap - INT
kill -INT $$

予想される動作を確認できます。

関連情報