Linux のプロセスでセグメンテーション エラーが発生しています。失敗したときにコア ダンプを生成するように指示するにはどうすればよいですか?
13 に答える
これは、使用しているシェルによって異なります。bash を使用している場合、ulimit コマンドは、コアをダンプするかどうかなど、プログラムの実行に関連するいくつかの設定を制御します。入力すると
ulimit -c unlimited
次に、そのプログラムが任意のサイズのコアをダンプできることをbashに伝えます。必要に応じて、無制限の代わりに 52M などのサイズを指定できますが、コア ファイルのサイズが問題になることはおそらくないため、実際にはこれは必要ありません。
tcsh では、次のように入力します。
limit coredumpsize unlimited
上記で説明したように、ここで実際に問われているのは、コア ダンプが有効になっていないシステムでコア ダンプを有効にする方法です。その質問はここで答えられます。
ハングしたプロセスのコア ダンプを生成する方法を学びたいと思ってここに来たのであれば、その答えは次のとおりです。
gcore <pid>
システムで gcore が利用できない場合
kill -ABRT <pid>
kill -SEGV を使用しないでください。シグナル ハンドラーが呼び出されることが多く、スタックしたプロセスの診断が難しくなります。
最後に、プロセスがクラッシュする前に gdb をプロセスにアタッチし、segfault が発生したときにgenerate-core-file
コマンドを実行しました。これにより、強制的にコア ダンプが生成されました。
このプログラムは、セグメンテーション違反をトラップしてデバッガにシェルを実行する方法のデモンストレーションであり (これは で使用されている元のコードですAIX
)、セグメンテーション違反のポイントまでのスタック トレースを出力します。Linux の場合、sprintf
使用する変数を変更する必要があります。gdb
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);
struct sigaction sigact;
char *progname;
int main(int argc, char **argv) {
char *s;
progname = *(argv);
atexit(cleanup);
init_signals();
printf("About to seg fault by assigning zero to *s\n");
*s = 0;
sigemptyset(&sigact.sa_mask);
return 0;
}
void init_signals(void) {
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGSEGV);
sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGBUS);
sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGQUIT);
sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGHUP);
sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGKILL);
sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}
static void signal_handler(int sig) {
if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
if (sig == SIGSEGV || sig == SIGBUS){
dumpstack();
panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
}
if (sig == SIGQUIT) panic("QUIT signal ended program\n");
if (sig == SIGKILL) panic("KILL signal ended program\n");
if (sig == SIGINT) ;
}
void panic(const char *fmt, ...) {
char buf[50];
va_list argptr;
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
va_end(argptr);
fprintf(stderr, buf);
exit(-1);
}
static void dumpstack(void) {
/* Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];
sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
/* Change the dbx to gdb */
system(dbx);
return;
}
void cleanup(void) {
sigemptyset(&sigact.sa_mask);
/* Do any cleaning up chores here */
}
このブログのこちらに示されているように、gdb がコアをダンプするようにパラメーターを追加する必要がある場合があります。
コア ダンプの生成に影響を与える可能性があるものは他にもあります。私はこれらに遭遇しました:
- ダンプのディレクトリは書き込み可能でなければなりません。デフォルトでは、これはプロセスの現在のディレクトリですが、設定によって変更される場合があります
/proc/sys/kernel/core_pattern
。 - 状況によっては、カーネル値が
/proc/sys/fs/suid_dumpable
原因でコアが生成されないことがあります。
マニュアルページに記載されている生成を妨げる状況は他にもあります - 試してみてくださいman core
。
コア ダンプを有効にするには、次の手順を実行します。
/etc/profile
コメントで次の行:# ulimit -S -c 0 > /dev/null 2>&1
次
/etc/security/limits.conf
の行をコメントアウトします。* soft core 0
cmd を実行し、 cmd
limit coredumpsize unlimited
で確認しlimit
ます。# limit coredumpsize unlimited # limit cputime unlimited filesize unlimited datasize unlimited stacksize 10240 kbytes coredumpsize unlimited memoryuse unlimited vmemoryuse unlimited descriptors 1024 memorylocked 32 kbytes maxproc 528383 #
コアファイルが書き込まれるかどうかを確認するには、関連するプロセスを cmd で強制終了できます
kill -s SEGV <PID>
(コア ファイルが書き込まれない場合に備えて、これをチェックとして使用できます)。# kill -s SEGV <PID>
コアファイルが書き込まれたら、関連ファイル (1./2./3.) でコアダンプ設定を再度無効にしてください。
デフォルトでは、コア ファイルが取得されます。プロセスの現在のディレクトリが書き込み可能であること、またはコア ファイルが作成されないことを確認してください。