I have a process in Linux that's getting a segmentation fault. How can I tell it to generate a core dump when it fails?
问题:
回答1:
This depends on what shell you are using. If you are using bash, then the ulimit command controls several settings relating to program execution, such as whether you should dump core. If you type
ulimit -c unlimited then that will tell bash that its programs can dump cores of any size. You can specify a size such as 52M instead of unlimited if you want, but in practice this shouldn't be necessary since the size of core files will probably never be an issue for you.
In tcsh, you'd type
limit coredumpsize unlimited 回答2:
As explained above the real question being asked here is how to enable core dumps on a system where they are not enabled. That question is answered here.
If you've come here hoping to learn how to generate a core dump for a hung process, the answer is
gcore if gcore is not available on your system then
kill -ABRT Don't use kill -SEGV as that will often invoke a signal handler making it harder to diagnose the stuck process
回答3:
What I did at the end was attach gdb to the process before it crashed, and then when it got the segfault I executed the generate-core-file command. That forced generation of a core dump.
回答4:
Maybe you could do it this way, this program is a demonstration of how to trap a segmentation fault and shells out to a debugger (this is the original code used under AIX) and prints the stack trace up to the point of a segmentation fault. You will need to change the sprintf variable to use gdb in the case of Linux.
#include #include #include #include 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 */ } You may have to additionally add a parameter to get gdb to dump the core as shown here in this blog here.
回答5:
There are more things that may influence the generation of a core dump. I encountered these:
- the directory for the dump must be writable. By default this is the current directory of the process, but that may be changed by setting
/proc/sys/kernel/core_pattern. - in some conditions, the kernel value in
/proc/sys/fs/suid_dumpablemay prevent the core to be generated.
There are more situations which may prevent the generation that are described in the man page - try man core.
回答6:
To check where the core dumps are generated, run:
sysctl kernel.core_pattern where %e is the process name and %t the system time. You can change it in /etc/sysctl.conf and reloading by sysctl -p.
If the core files are not generated (test it by: sleep 10 & and killall -SIGSEGV sleep), check the limits by: ulimit -a.
If your core file size is limited, run:
ulimit -c unlimited to make it unlimited.
Then test again, if the core dumping is successful, you will see “(core dumped)” after the segmentation fault indication as below:
Segmentation fault: 11 (core dumped)
Ubuntu
In Ubuntu usually the dumps are handled by apport in /var/crash/, but in different format, however it's not enabled by default in stable releases. Read more at Ubuntu wiki.
It uses core_pattern to directly pipe the core dump into apport:
$ cat /proc/sys/kernel/core_pattern |/usr/share/apport/apport %p %s %c So even core files are disabled by ulimit, apport will still capture the crash (How do I enable or disable Apport?).
macOS
For macOS, see: How to generate core dumps in Mac OS X?
回答7:
In order to activate the core dump do the following:
In
/etc/profilecomment the line:# ulimit -S -c 0 > /dev/null 2>&1In
/etc/security/limits.confcomment out the line:* soft core 0execute the cmd
limit coredumpsize unlimitedand check it with cmdlimit:# 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 #to check if the corefile gets written you can kill the relating process with cmd
kill -s SEGV(should not be needed, just in case no core file gets written this can be used as a check):# kill -s SEGV
Once the corefile has been written make sure to deactivate the coredump settings again in the relating files (1./2./3.) !
回答8:
By default you will get a core file. Check to see that the current directory of the process is writable, or no core file will be created.
回答9:
For Ubuntu 14.04
Check core dump enabled:
ulimit -aOne of the lines should be :
core file size (blocks, -c) unlimitedIf not :
gedit ~/.bashrcand addulimit -c unlimitedto end of file and save, re-run terminal.Build your application with debug information :
In Makefile
-O0 -gRun application that create core dump (core dump file with name ‘core’ should be created near application_name file):
./application_nameRun under gdb:
gdb application_name core