35

おそらくファイル記述子のリークがあるプロセスからのコアダンプファイルがあります(ファイルとソケットを開きますが、それらのいくつかを閉じるのを忘れているようです)。クラッシュする前にプロセスが開いていたファイルとソケットを見つける方法はありますか? クラッシュを簡単に再現することはできないため、コア ファイルを分析することがバグのヒントを得る唯一の方法のようです。

4

8 に答える 8

11

コアファイルがあり、デバッグオプション(-g)を使用してプログラムをコンパイルした場合は、コアがダンプされた場所を確認できます。

$ gcc -g -o something something.c
$ ./something
Segmentation fault (core dumped)
$ gdb something core

これを使用して、事後デバッグを行うことができます。いくつかのgdbコマンド:btはスタックを出力し、frは指定されたスタックフレームにジャンプします(btの出力を参照)。

ここで、セグメンテーション違反で開かれているファイルを確認したい場合は、SIGSEGVシグナルを処理し、ハンドラーで/ proc / PID / fdディレクトリの内容をダンプします(つまり、system('ls -l / proc / PID / fs')またはexecv)。

これらの情報が手元にあれば、クラッシュの原因、開いているファイル、クラッシュとファイル記述子のリークが関連しているかどうかを簡単に見つけることができます。

于 2008-09-15T18:43:05.913 に答える
5

最善の策は、プログラムをクラッシュさせているシグナル (SIGSEGV など) のシグナル ハンドラーをインストールすることです。

次に、シグナル ハンドラーで /proc/self/fd を検査し、内容をファイルに保存します。表示されるサンプルを次に示します。

Anderson cxc # ls -l  /proc/8247/fd
total 0
lrwx------ 1 root root 64 Sep 12 06:05 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 1 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 10 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Sep 12 06:05 11 -> socket:[124061]
lrwx------ 1 root root 64 Sep 12 06:05 12 -> socket:[124063]
lrwx------ 1 root root 64 Sep 12 06:05 13 -> socket:[124064]
lrwx------ 1 root root 64 Sep 12 06:05 14 -> /dev/driver0
lr-x------ 1 root root 64 Sep 12 06:05 16 -> /temp/app/whatever.tar.gz
lr-x------ 1 root root 64 Sep 12 06:05 17 -> /dev/urandom

その後、シグナル ハンドラーから戻ることができ、通常どおりコア ダンプを取得する必要があります。

于 2008-09-12T13:55:25.630 に答える
4

この情報にジャンプする方法の 1 つはstrings、コア ファイルを実行することです。たとえば、最近コアでファイルを実行していたとき、フォルダーの長さが原因で、切り捨てられた引数リストを取得していました。実行するとホームディレクトリからファイルが開かれることがわかっていたので、次のように実行しました。

strings core.14930|grep jodie

しかし、これは私が針と干し草の山を持っていた場合です。

于 2014-12-19T01:09:11.687 に答える
3

を使用して、プログラムが行う呼び出しをstrace確認できます。opensocketclose

編集:コアから情報を取得できるとは思いません。せいぜいどこかにファイル記述子がありますが、それでも実際のファイル/ソケットは得られません。(開いているファイル記述子と閉じているファイル記述子を区別できると仮定しますが、これも疑問です。)

于 2008-09-12T09:53:50.500 に答える
2

プログラムがこれらのリソースを閉じるのを忘れた場合、次のようなことが起こったことが原因である可能性があります。

fd = open("/tmp/foo",O_CREAT);
//do stuff
fd = open("/tmp/bar",O_CREAT); //Oops, forgot to close(fd)

これで、メモリ内に foo のファイル記述子がなくなります。

これが起こらなかった場合、ファイル記述子番号を見つけることができるかもしれませんが、繰り返しますが、それらは継続的に変化しているため、あまり役に立ちません。デバッグするまでに、実際にどのファイルを意味するのかわからなくなります当時の。

strace、lsof、および友人と一緒に、これをライブでデバッグする必要があると本当に思います。

コアダンプからそれを行う方法があれば、私もそれを知りたいと思っています:-)

于 2008-09-12T10:15:05.363 に答える
1

コア ダンプは、クラッシュ時にプロセスがアクセスしていたメモリのコピーです。リークの発生状況によっては、ハンドルへの参照が失われている可能性があるため、役に立たないことが判明する可能性があります。

lsof は、システムで現在開いているすべてのファイルを一覧表示します。その出力をチェックして、リークされたソケットまたはファイルを見つけることができます。はい、プロセスを実行する必要があります。特定のユーザー名で実行して、デバッグ中のプロセスから開いているファイルを簡単に識別することができます。

他の誰かがより良い情報を持っていることを願っています:-)

于 2008-09-12T09:50:07.610 に答える
0

プロセスが開いたファイルを確認するもう 1 つの方法 (実行時のみ) は、開いているファイルへのシンボリック リンクを含む /proc/PID/fd/ を調べます。

于 2008-09-12T09:56:03.210 に答える