Linuxでセグメンテーション違反が発生しているプロセスがあります。失敗したときにコアダンプを生成するようにするにはどうすればよいですか?
Linuxでセグメンテーション違反が発生しているプロセスがあります。失敗したときにコアダンプを生成するようにするにはどうすればよいですか?
回答:
これは、使用しているシェルによって異なります。bashを使用している場合、ulimitコマンドは、コアをダンプするかどうかなど、プログラムの実行に関連するいくつかの設定を制御します。入力した場合
ulimit -c unlimited
次に、そのプログラムは任意のサイズのコアをダンプできることをbashに伝えます。必要に応じて、無制限ではなく52Mなどのサイズを指定できますが、コアファイルのサイズが問題になることはおそらくないため、実際にはこれは必要ありません。
tcshでは、次のように入力します
limit coredumpsize unlimited
上記で説明したように、ここで尋ねられる実際の質問は、コアダンプが有効になっていないシステムでコアダンプを有効にする方法です。その質問はここで答えられます。
ハングしたプロセスのコアダンプを生成する方法を学びたいと思っているなら、答えは
gcore <pid>
システムでgcoreが利用できない場合
kill -ABRT <pid>
kill -SEGVを使用しないでください。シグナルハンドラーが頻繁に呼び出され、スタックプロセスの診断が難しくなります。
-ABRT
ので-SEGV
、シグナルハンドラを呼び出す方がはるかに可能性が高いと思います。(segfaultを処理する場合、通常はハンドラーが終了するとすぐに再びトリガーされます。)コアダンプを生成するためのより適切な信号の選択は-QUIT
です。
コアダンプが生成される場所を確認するには、次のコマンドを実行します。
sysctl kernel.core_pattern
または:
cat /proc/sys/kernel/core_pattern
どこ%e
プロセス名とで%t
システム時刻は。あなたはそれを変更し/etc/sysctl.conf
てリロードすることができますsysctl -p
。
コアファイルが生成されない場合(それをテストする:sleep 10 &
およびkillall -SIGSEGV sleep
)、次の方法で制限を確認します。ulimit -a
。
コアファイルのサイズが限られている場合は、次を実行します。
ulimit -c unlimited
無制限にします。
次に、再度テストします。コアダンプが成功した場合、次のようにセグメンテーションエラー表示の後に「(コアダンプ)」が表示されます。
セグメンテーションエラー:11(コアダンプ)
参照:コアダンプ-コアファイルが現在のディレクトリにありませんか?
Ubuntuでは、コアダンプはApportによって処理され、次の場所にあります。/var/crash/
。ただし、安定版リリースではデフォルトで無効になっています。
詳細については、Ubuntuのコアダンプはどこにありますか?。
macOSについては、「Mac OS Xでコアダンプを生成する方法」を参照してください。
最後に、クラッシュする前にgdbをプロセスにアタッチし、segfaultが取得されたときにgenerate-core-file
コマンドを実行しました。これにより、コアダンプが強制的に生成されました。
ge
)
ulimit -c
ていunlimited
ますが、コアファイルはまだ作成されていません。gdb 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を取得するためのパラメーターを追加する必要がある場合があります。
コアダンプをアクティブにするには、次の手順を実行します。
/etc/profile
コメント行:
# ulimit -S -c 0 > /dev/null 2>&1
で/etc/security/limits.conf
ラインアウトのコメント:
* soft core 0
cmd limit coredumpsize unlimited
を実行し、cmd で確認し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
#
kill -s SEGV <PID>
コアファイルが書き込まれるかどうかを確認するには、関連するプロセスをcmdで強制終了できます(コアファイルが書き込まれない場合に備えて、これをチェックとして使用できます)。
# kill -s SEGV <PID>
コアファイルが作成されたら、関連ファイル(1./2./3。)でコアダンプ設定を必ず非アクティブ化してください。
Ubuntu 14.04の場合
有効なコアダンプを確認します。
ulimit -a
行の1つは次のようになります。
core file size (blocks, -c) unlimited
そうでない場合:
gedit ~/.bashrc
ulimit -c unlimited
ファイルの最後に追加して保存し、ターミナルを再実行します。
デバッグ情報を使用してアプリケーションをビルドします。
Makefile内 -O0 -g
コアダンプを作成するアプリケーションを実行します( 'core'という名前のコアダンプファイルは、application_nameファイルの近くに作成する必要があります)。
./application_name
gdbの下で実行します。
gdb application_name core
ulimit -c unlimited
です。一時的な解決策としてターミナルに配置するだけでもよいようです~/.bashrc
。変更を有効にするには、ターミナルのレストラートのみ編集が必要なためです。
デフォルトでは、コアファイルを取得します。プロセスの現在のディレクトリが書き込み可能であるか、コアファイルが作成されないかを確認します。
システムコールを使用してプログラムでコアダンプをオンにすることをお勧めしますsetrlimit
。
例:
#include <sys/resource.h>
bool enable_core_dump(){
struct rlimit corelim;
corelim.rlim_cur = RLIM_INFINITY;
corelim.rlim_max = RLIM_INFINITY;
return (0 == setrlimit(RLIMIT_CORE, &corelim));
}
ulimit -c unlimited
コマンドライン環境で実行する必要はなく、アプリケーションを再実行します。
ulimit -c unlimited
。また、marco定義を使用してコンパイルできます。enable_core_dump
リリース時にそのマクロを定義しないと、アプリケーションにシンボルが含まれず、デバッグバージョンでコアダンプが置き換えられます。
systemdが設定されている場合、状況が少し異なることに言及する価値があります。通常、セットアップでは、core_pattern
sysctl値を使用して、コアファイルをパイプ処理します。systemd-coredump(8)
。コアファイルサイズrlimitは通常、「無制限」としてすでに構成されています。
その後、次のコマンドを使用してコアダンプを取得できます。 coredumpctl(1)
。
コアダンプなどのストレージは、 coredump.conf(5)
ます。coredumpctlのmanページにコアファイルを取得する方法の例がありますが、簡単に言うと次のようになります。
コアファイルを見つけます。
[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET 16163 1224 1224 11 present /home/vps/test_me
コアファイルを取得します。
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
他のすべての回答自体は私を助けませんでした。しかし、次の要約は仕事をしました
~/.config/apport/settings
次の内容で作成します。
[main]
unpackaged=true
(これにより、カスタムアプリのコアダンプも書き込むようにapportに指示されます)
チェック:ulimit -c
。それが0を出力する場合、それを修正します
ulimit -c unlimited
念のためにapportを再起動してください:
sudo systemctl restart apport
クラッシュファイルがで書き込まれるようになりました/var/crash/
。ただし、gdb では使用できません。これらをgdbで使用するには、
apport-unpack <location_of_report> <target_directory>
さらに詳しい情報:
core_pattern
ます。このファイルは、再起動時にapportサービスによって上書きされる可能性があることに注意してください。ulimit -c
ウェブの他の回答を試しているときに、値が自動的に変更される場合があります。コアダンプ作成の設定中は、定期的に確認してください。参照: