2013年1月19日土曜日

bashでSIGCHLDをハンドル

trapコマンドを使用するとシグナル受けて動作することができる。

#!/bin/bash
trap 'echo SIGINT trapped.' SIGINT
sleep 1000
スクリプトを実行後Ctrl+Cを入力するとechoが表示される

^CSIGINT trapped.

また、bashでは擬似シグナルという仕組みが実装されており、
bashの終了やコマンドのエラーをtrapすることができる。

#!/bin/bash

trap 'echo ScriptExit.' EXIT
echo "Hello"

スクリプトの最終行のHello実行後にEXITがtrapされている。

Hello
ScriptExit.

で、ここからが本題。
この仕組みを利用してSIGCHLD(子プロセスの終了)をハンドリングしたかったのだけど
意図したとおりに動かない。
こんな感じ。

#!/bin/bash

trap 'echo GetSIGCHLD.' SIGCHLD
echo "SCIRPT_END"

期待動作はSCIRPT_ENDの前にGetSIGCHLDが表示されて欲しいが、 実際の出力結果は以下のとおり

PID TTY          TIME CMD
20082 pts/3    00:00:00 bash
20486 pts/3    00:00:00 sample.script
20487 pts/3    00:00:00 ps
SCIRPT_END

SIGCHLDがtrapされていないように見える。
で、いろいろ調べてどうもbashには動作モードがあり
モニターモードに設定していないとSIGCHLDがtrapできないらしい。
それを修正すると。
#!/bin/bash

set -m  # monitor mode set
trap 'echo GetSIGCHLD.' SIGCHLD
ps
echo "SCIRPT_END"

PID TTY          TIME CMD
20082 pts/3    00:00:00 bash
20500 pts/3    00:00:00 sample.scrip
20501 pts/3    00:00:00 ps

GetSIGCHLD.

SCIRPT_END

期待通り!
今度bashのモードについて調べてみよう。

0 件のコメント:

コメントを投稿