Giám sát dump core linux

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.

Show
#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.

Environment

  • Red Hat Enterprise Linux 5
  • Red Hat Enterprise Linux 4
  • Red Hat Enterprise Linux 3
  • For Red Hat Enterprise Linux 6, 7, 8 , please refer the NOTE in the resolution section.

Issue

  • How to enable core file dumps when an application crashes or segmentation faults (segfault)
  • How to configure core dumps in Red Hat Enterprise Linux
  • How to generate a core dump in Red Hat Enterprise Linux

Resolution

Note:- There are a couple of ways to enable core file creation. Below methods may conflict with abrt-* services, please use them with abrt-* services stopped and disabled.

Preferred method

  1. Replace the above ulimit command in /etc/profile with the following (this will allow all users to produce core files of unlimited size):

    # ulimit -S -c unlimited > /dev/null 2>&1
    
  2. To disallow users of the system to be able to dump core files, configure the /etc/security/limits.conf file to allow only certain users or groups to create core files. For example, if all the members of the "devel" group are to be allowed to dump core files:

    #<domain> <type>  <item>  <value>
    @devel   soft   core    <value>
    
  3. The field < value > is the maximum block size of a core file. The /etc/security/limits.conf file is well documented with usage and options at the top of the file. Please note that for these settings to be honored, it is necessary to comment out the above mentioned ulimit command in the /etc/profile file as follows:

    # No core files by default
    # ulimit -S -c 0 > /dev/null 2>&1
    
  4. If this application is being started within its init script with the daemon command, edit the /etc/init.d/functions file to comment out or change this line:

    # ulimit -S -c 0 >/dev/null 2>&1
    
  • With this setup, a core file from the application should result. If this does not generate a core, make sure that the application has the correct uid and that it does not use setuid to change uid when running.

    • RHEL 3, use the following command to enable the dumping of setuid applications:

          # echo 1 > /proc/sys/kernel/core_setuid_ok
      
    • Other RHEL version, use following sysctl settings in /etc/sysctl.conf. The core_pattern below is just an example.

      kernel.core_pattern=/var/crash/core_%e_%p_%h_%t
      kernel.core_uses_pid=1
      fs.suid_dumpable=1
      

Alternate method

1, The following method has been provided by Red Hat, but is outside the scope of the posted Service Level Agreements and support procedures.

  1. Add the following call to the application source (in the C language):

        prctl(PR_SET_DUMPABLE, 1);
    

Notes

  • By default, core files are created in the working directory of the faulting application. To override this and specify a location for the files, enter the following command (as root) replacing "/tmp" with the desired target directory:

    # echo "/tmp/core" > /proc/sys/kernel/core_pattern
    

    This will generate a core file under /tmp as:

    core.$PID
    
  • If you change to non-root user test via su - test and found the setting core size not effect via ulimit -a , you could check the /etc/profile and comment out the ulimit -S -c 0 > /dev/null 2>&1

    # No core files by default
    # ulimit -S -c 0 > /dev/null 2>&1
    
  • For Red Hat Enterprise Linux 6, refer How to collect core dump file of a crashing program that is shipped in Red Hat Enterprise Linux 6/7/8?

    • For background on segmentation faults, refer to A Guide for Troubleshooting a Segfault
    • Refer What to do if a third party application segfaults if it is a third party application.
    • For some services this configuration not works, such as sendmail. In this case, please comment out corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}" in /etc/init.d/function and try again:

      # kill -11 <pid>
      
  • For Red Hat Enterprise Linux 7/8, refer How to collect core dump file of a crashing program that is shipped in Red Hat Enterprise Linux 6/7/8?

    • The limit is set by systemd, add the following setting in /etc/systemd/system.conf can be set it as unlimited.

      DefaultLimitCORE=infinity
      
    • Run systemctl daemon-reexec or reboot the system

  • For Daemon process

    • Refer How to enable coredumps for daemon process (services) in RHEL?

Root Cause

  • In Red Hat Enterprise Linux core file creation is disabled by default. This is done by the following ulimit command in /etc/profile:

    # ulimit -S -c 0 > /dev/null 2>&1
    

  • Product(s)
  • Red Hat Enterprise Linux
  • Component
  • dump
  • Category
  • Configure
  • Tags
  • crash
  • rhel_4
  • rhel_5
  • rhel_6

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.