0

gdb を使用してデバッグした場合とそうでない場合で、動作が異なる単純な C プログラムがあります。プログラムは次のとおりです。

#include <stdio.h>
#include <signal.h>

int main() {
    kill(getpid(), SIGFPE);
    printf("I'm happy.\n");
    return 0;
}

単独で実行すると、次の非常に奇妙な結果が得られます。

ezyang@javelin:~$ ./mini
私は満足しています。
ezyang@javelin:~$ echo $?
0

エラーなし!これは、シグナルが発せられていないということではありません。

ezyang@javelin:~$ strace -e signal ./mini
殺す (31950、SIGFPE) = 0
--- SIGFPE (浮動小数点例外) @ 0 (0) ---
私は満足しています

GDB では、状況が異なります。

ezyang@javelin:~/Dev/ghc-build-sandbox/libraries/unix/tests/libposix$ gdb ./mini
GNU gdb (GDB) 7.5.91.20130417-cvs-ubuntu
Copyright (C) 2013 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 以降
これはフリー ソフトウェアです。自由に変更して再配布してください。
法律で許可されている範囲で、保証はありません。「コピーを表示」と入力します
詳細については、「保証を表示する」を参照してください。
この GDB は「x86_64-linux-gnu」として構成されました。
バグ報告の手順については、次を参照してください。
...
/srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini からシンボルを読み取り中...(デバッグ シンボルが見つかりません)...完了。
(gdb) r
プログラムの開始: /srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini
警告: 0x7ffff7ffa000 に追加されたシンボル ファイル システム提供の DSO に読み込み可能なセクションが見つかりません

プログラムは、シグナル SIGFPE、算術例外を受け取りました。
kill () の 0x00007ffff7a49317 at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: そのようなファイルまたはディレクトリはありません。
(gdb)c
つづく。

プログラムはシグナル SIGFPE、算術例外で終了しました。
プログラムはもう存在しません。

GDBに停止しないように依頼しても違いはありません

(gdb) SIGFPE nostop を処理する
シグナル ストップ プリント プログラムへのパス 説明
SIGFPE いいえ はい はい 算術例外
(gdb) r
プログラムの開始: /srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini
警告: 0x7ffff7ffa000 に追加されたシンボル ファイル システム提供の DSO に読み込み可能なセクションが見つかりません

プログラムは、シグナル SIGFPE、算術例外を受け取りました。

プログラムはシグナル SIGFPE、算術例外で終了しました。
プログラムはもう存在しません。

どうしたの?!1 つには、SIGFPE がプログラムを強制終了しないのはなぜですか。次に、GDB の動作が異なるのはなぜですか?

アップデート。考えられることの 1 つは、子プロセスが親プロセスのシグナル マスクを継承していることです。 しかし、このトランスクリプトに見られるように、明らかにそうではありません。 この分析は正しくありませんでした。以下を参照してください。

ezyang@javelin:~$ トラップ - SIGFPE
ezyang@javelin:~$ ./mini
私は満足しています。

更新 2.私の友人は、trap が親プロセスではなく、シェル自体によって設定されたシグナルのみを報告することを指摘しています。そこで、すべての親の無視マスクを追跡したところ、見よ、rxvt-unicode には SIGFPE がマスクされていました。友人は、rxvt-unicode を使用して実行可能ファイルを実行すると、再現できることを確認しました。

4

2 に答える 2

2

無視されたシグナルは、 と の間で継承さfork()exec*()ます。

$ ./ミニ
浮動小数点例外 (コアダンプ)
$ トラップ '' SIGFPE
$ ./ミニ
私は満足しています。
$ トラップ - SIGFPE
$ ./ミニ
浮動小数点例外 (コアダンプ)

これについて、質問の作成者と個人的に話し合いました。デバッグは、bash がその親プロセスからシグナル マスクを保存および復元するという事実と、親プロセスから継承された無視されたシグナルが引き続き有効であっても、現在のシェルでtrap処理または無視されたシグナルのみをビルトインが報告するという事実によって複雑でした。

根本的な問題は、無条件に SIGFPEを無視する libperl をリンクする urxvt 内でテストを実行していたことでした。

于 2013-07-20T20:49:46.043 に答える
0

のシグナル マスクとシグナル処理はSIG_IGN、子プロセスに継承されます。考えられる唯一の可能性は、シェルがSIGFPE何らかの理由でマスクまたは無視されており、プログラムを開始する前にこのステータスをクリアしていないことです。

于 2013-07-20T20:08:43.173 に答える