web-dev-qa-db-ja.com

139(セグメンテーション違反)を返すプログラムをbashでトラップするにはどうすればよいですか?

一部のプログラムをテストするbashスクリプトがあり、プログラムの1つがSegmentation faultを返すため、スクリプトの先頭にトラップを追加しようとしました。

trap "echo 'segfault occured!'" SIGSEGV

しかし、それは何もしませんでした。使った

echo $?

segfaultを生成するプログラムの直後に、出力として139が表示されます。特定のエラーコードのトラップを追加するにはどうすればよいですか?

10
Pithikos

trap "$instructions" SIGSEGVは、シェル自体のセグメンテーション違反をトラップします。

set -eの下でスクリプトを実行する場合、EXIT(または0)にトラップを設定できます。これは、スクリプトが終了したときに実行されます(コマンドがゼロ以外のステータスを返したためか、明示的にexitを呼び出した場合か、スクリプトの最後から落ちた場合)。セグメンテーション違反をテストするには、トラップへの入り口で$?を確認します。 ($?は、プログラムがステータス139で正常に戻ったため、139になる可能性があることに注意してください。これは、シェルで処理を行う場合は回避できます。)

set -e
trap 'case $? in
        139) echo "segfault occurred";;
      esac' EXIT

Bashまたはkshまたはzshでは、ゼロ以外のステータスを返す各コマンドの後にトラップを実行するためにset -eを使用する必要はありません。代わりにERRにトラップを置くことができます。以前と同様に、トラップへの入り口で$?を確認する必要があります。139は、プログラムがこのステータスを返したことを意味する場合があります(ほとんどありません)。

man bashから:

   trap [-lp] [[arg] sigspec ...]
          The command arg is to  be  read  and  executed  when  the  Shell
          receives  signal(s)  sigspec.

プログラムがsegfaultを実行すると、何らかの方法で子が終了したため、bashはSIGCHLDを取得します。

ただし、$?に格納されている終了コードを条件付きで使用して、SIGCHLDをトラップすることができます。

trap 'if [[ $? -eq 139 ]]; then echo "segfault !"; fi' CHLD

set -bmが非インタラクティブbash(スクリプトなど)で使用されている場合(おそらくそれが何であるか)が必要になる場合があることに注意してください。

編集:bashtrap

6
sr_