How to generate a core dump in Linux on a segmentation fault?

前端 未结 12 1132
余生分开走
余生分开走 2020-11-22 17:06

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?

相关标签:
12条回答
  • 2020-11-22 17:40

    To check where the core dumps are generated, run:

    sysctl kernel.core_pattern
    

    or:

    cat /proc/sys/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)

    See also: core dumped - but core file is not in current directory?


    Ubuntu

    In Ubuntu the core dumps are handled by Apport and can be located in /var/crash/. However, it is disabled by default in stable releases.

    For more details, please check: Where do I find the core dump in Ubuntu?.

    macOS

    For macOS, see: How to generate core dumps in Mac OS X?

    0 讨论(0)
  • 2020-11-22 17:40

    Better to turn on core dump programmatically using system call setrlimit.

    example:

    #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));
    }
    
    0 讨论(0)
  • 2020-11-22 17:41

    In order to activate the core dump do the following:

    1. In /etc/profile comment the line:

      # ulimit -S -c 0 > /dev/null 2>&1
      
    2. In /etc/security/limits.conf comment out the line:

      *               soft    core            0
      
    3. execute the cmd limit coredumpsize unlimited and check it with 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
      #
      
    4. to check if the corefile gets written you can kill the relating process with cmd kill -s SEGV <PID> (should not be needed, just in case no core file gets written this can be used as a check):

      # kill -s SEGV <PID>
      

    Once the corefile has been written make sure to deactivate the coredump settings again in the relating files (1./2./3.) !

    0 讨论(0)
  • 2020-11-22 17:42

    For Ubuntu 14.04

    1. Check core dump enabled:

      ulimit -a
      
    2. One of the lines should be :

      core file size          (blocks, -c) unlimited
      
    3. If not :

      gedit ~/.bashrc and add ulimit -c unlimited to end of file and save, re-run terminal.

    4. Build your application with debug information :

      In Makefile -O0 -g

    5. Run application that create core dump (core dump file with name ‘core’ should be created near application_name file):

      ./application_name
      
    6. Run under gdb:

      gdb application_name core
      
    0 讨论(0)
  • 2020-11-22 17:43

    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
    
    0 讨论(0)
  • 2020-11-22 17:43

    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 <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 */
    }
    

    You may have to additionally add a parameter to get gdb to dump the core as shown here in this blog here.

    0 讨论(0)
提交回复
热议问题