web-dev-qa-db-ja.com

Linuxプロセスは、子に送信された信号を傍受できますか?

大きな実行可能ファイルの周りにシェルラッパーがあります。それはこのようなことをします:

_run/the/real/executable "$@" &
PID=$!
# perform
# a few
# minor things
wait $PID
# perform some
# post-processing
_

waitの後に実行することの1つは、コアダンプをチェックし、プロセスのクラッシュを処理することですが、それまでにプロセスはすでに停止しており、一部の情報は利用できなくなります。

致命的な信号(SIGSEGVまたはSIGBUS)は、子自体に配信される前にシェルスクリプトによって傍受できますか?

次に、たとえば、_lsof -p $PID_を実行して、ラップされたプロセスが停止する前に開いたファイルのリストを取得できます。

更新:シグナルを受信するプロセスをキャッチするためにstraceを使用してみました。残念ながら、人種が発生しているようです。straceが子の信号を報告すると、子は出て行く途中であり、lsofがファイルのリストを取得するかどうかはわかりません。か否か...

これがテストスクリプトです。このスクリプトは_/bin/sleep_を生成し、書き込み用に開いたファイルを取得しようとします。 _/tmp/sleep-output.txt_が正常に報告される場合もあれば、リストが空の場合もあります。

_ulimit -c 0
/bin/sleep 15 > /tmp/sleep-output.txt &

NPID=$!

echo "Me: $$, sleep: $NPID"

(sleep 3; kill -BUS $NPID) &

ps -ww $NPID
while read line
do
        set -x
        outputfiles=$(lsof -F an -b -w -p $NPID | sed -n '/^aw$/ {n; s,.,,; p}')
        ps -ww $NPID
        lsof -F an -b -w -p $NPID
        break
done < <(strace -qq -p $NPID -e trace=signal 2>&1)
echo $outputfiles

wait $NPID
_

上記のテストでは、kshまたはbashを使用する必要があります(< <(...)構造が機能するため)。

3
Mikhail T.

私の知る限り、あなたが試みていることを実行するためのシェルメソッドはありません。カスタムプログラムから実行する必要があります。

ptrace() を使用して、デバッガーと同様にプロセスを監視します。プロセスがシグナルを受信すると、シグナルは停止し、監視プログラムに通知されます(wait()の呼び出しが返され、WIFSTOPPED(status)がtrueになります)。

次に、_lsof -p <pid>_を実行してプロセスの開いているファイルを一覧表示し、ptrace(PTRACE_CONT, pid, NULL, 0)を呼び出してプロセスを再開できます。

2
Barmar