Core dump

From Attie's Wiki
Jump to: navigation, search

To enable core dumps, do this in a shell:

ulimit -c unlimited

Or this from C:

#include <sys/time.h>
#include <sys/resource.h>
 
void coredump_enable(void) {
  struct rlimit rlim;
  getrlimit(RLIMIT_CORE,&rlim);
  rlim.rlim_cur = rlim.rlim_max;
  setrlimit(RLIMIT_CORE,&rlim);
}
 
void coredump_disable(void) {
  struct rlimit rlim;
  getrlimit(RLIMIT_CORE,&rlim);
  rlim.rlim_cur = 0;
  setrlimit(RLIMIT_CORE,&rlim);
}

After you call coredump_enable(), if your program dies for any reason (Segfault, etc) then a core dump will be taken. It will often be stored to ./code but the naming schema can be changed. BEWARE: once a dump has been taken, if the naming schema does not result in a unique name, then an existing dump (or file) will NOT be overwritten.

Contents

Creating a core dump

SIGQUIT is usually bound to ^\. If it's not being masked and core dumps are enabled, then you should get a dump in your current directory.

Alternatively, use kill -QUIT ${PID} or kill -ABRT ${PID}

From within GDB

generate-core-file [file]

Naming the core dumps

Run the following to see your current setting:

cat /proc/sys/kernel/core_pattern

And run the following (as root) to update it:

echo "%e.core.%s.%p" > /proc/sys/kernel/core_pattern

Putting a '|' (pipe) before an executable path and parameters from below in here allows you to run a script on a crash! That is executed before the application is killed! Be careful, that application is run as root, as a child of 'keventd'. Info

Pattern replacement

 %p pid
 %% output one '%'
 %u uid
 %g gid
 %s signal number
 %t UNIX time of dump
 %h hostname
 %e executable filename
 %<OTHER> both are dropped
 %<NUL> '%' is dropped

Permanent Configuration

You can add a line like this to /etc/sysctl.conf:

kernel.core_pattern = "%e.core.%s.%p"

Core Dump a Running Process

  1. Check /proc/${PID}/limits
  2. SIGQUIT - kill -QUIT ${PID}

Analyzing the dump later

Take your executable in the left hand, and the core in the right, and shove them at gdb:

gdb ${EXECUTABLE} ${COREDUMP}

Initiate a dump from C

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
 
void dump_core(void) {
  pid_t cpid, rpid;
  int status;
 
  cpid = fork();
 
  if (cpid == -1) {
    /* fork failed... */
    fprintf(stderr, "dump_core(): failed to fork...\n");
  }
 
  if (cpid == 0 || cpid == -1) {
    /* in the child or fork()-failed process... */
    struct rlimit rlim;
    rlim_t t;
 
    /* ensure that a dump will be created by setting RLIMIT_CORE... */
    if (getrlimit(RLIMIT_CORE, &rlim) == -1) {
      fprintf(stderr, "dump_core(): failed to query RLIMIT_CORE... continuing to attempt a core dump...\n");
    } else {
      if (rlim.rlim_max == 0) {
        fprintf(stderr, "dump_core(): rlim_max is set to 0... we can't create a core dump...\n");
        if (cpid == -1) return;
        exit(42);
      } else if (rlim.rlim_max != RLIM_INFINITY) {
        fprintf(stderr, "dump_core(): rlim_max is not RLIM_INFINITY... limited to a dump of %ldx 512-byte blocks...\n", rlim.rlim_max);
      }
      t = rlim.rlim_cur;
      rlim.rlim_cur = rlim.rlim_max;
      if (setrlimit(RLIMIT_CORE, &rlim) == -1) {
        fprintf(stderr, "dump_core(): failed to set RLIMIT_CORE...\n");
        if (t == 0) {
          fprintf(stderr, "dump_core(): rlim_cur was set to 0... we can't create a core dump...\n");
          if (cpid == -1) return;
          exit(42);
        } else if (t != RLIM_INFINITY) {
          fprintf(stderr, "dump_core(): rlim_cur is not RLIM_INFINITY... limited to a dump of %ldx 512-byte blocks...\n", t);
        }
      }
    }
 
    /* and crash in your favorite way! */
    abort();
    (*((int*)0)) = 42;
    exit(-1);
  }
 
  /* wait for the child to go away (die) */
  if ((rpid = waitpid(cpid, &status, 0)) == -1) {
    fprintf(stderr, "dump_core(): failed to wait for the child...\n");
  } else if (rpid == 0) {
    fprintf(stderr, "dump_core(): somehow waitpid() returned with no notification...\n");
  } else if (rpid != cpid) {
    fprintf(stderr, "dump_core(): somehow waitpid() returned a notification for the wrong child...\n");
  } else {
    if (WIFEXITED(status)) {
      if (WEXITSTATUS(status) == 42) {
        fprintf(stderr, "dump_core(): failed to create a core dump...\n");
      } else {
        fprintf(stderr, "dump_core(): child returned with %d (unexpected...)\n", WEXITSTATUS(status));
      }
    } else if (WIFSIGNALED(status)) {
      if (WCOREDUMP(status)) {
        /* if everything goes to plan, this should be all you'll see: */
        fprintf(stderr, "dump_core(): successfully created a core dump!\n");
      } else {
        fprintf(stderr, "dump_core(): apparently no core dump was created... :-(\n");
      }
    }
  }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox