Как создать дамп ядра в Linux при ошибке сегментации? - PullRequest
195 голосов
/ 20 августа 2008

У меня есть процесс в Linux, который получает ошибку сегментации. Как я могу сказать ему генерировать дамп ядра при сбое?

Ответы [ 12 ]

230 голосов
/ 20 августа 2008

Это зависит от того, какую оболочку вы используете. Если вы используете bash, то команда ulimit контролирует несколько параметров, связанных с выполнением программы, например, следует ли вам выгружать ядро. Если вы наберете

ulimit -c unlimited

тогда это скажет bash, что его программы могут выгружать ядра любого размера. Вы можете указать размер, например, 52 МБ, а не неограниченный, если хотите, но на практике это не требуется, поскольку размер основных файлов, вероятно, никогда не будет проблемой для вас.

В tcsh вы наберете

limit coredumpsize unlimited
54 голосов
/ 05 февраля 2013

Как объяснено выше, реальный вопрос, который здесь задают, заключается в том, как включить дамп ядра в системе, где они не включены. На этот вопрос ответ здесь.

Если вы пришли сюда в надежде узнать, как создать дамп ядра для зависшего процесса, ответ будет

gcore <pid>

если gcore недоступен в вашей системе, то

kill -ABRT <pid>

Не используйте kill -SEGV, так как это часто вызывает обработчик сигнала, затрудняя диагностику застрявшего процесса

24 голосов
/ 08 сентября 2015

Чтобы проверить, где генерируются дампы ядра, запустите:

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

В Ubuntu дампы ядра обрабатываются Apport и могут находиться в /var/crash/. Однако он по умолчанию отключен в стабильных выпусках.

Для более подробной информации, пожалуйста, проверьте: Где найти дамп ядра в Ubuntu? .

1047 * MacOS * Для macOS см .: Как создать дамп ядра в Mac OS X?

24 голосов
/ 20 августа 2008

В конце концов я подключил gdb к процессу до его сбоя, а затем, когда он получил ошибку segfault, выполнил команду generate-core-file. Это принудительное создание дампа ядра.

19 голосов
/ 26 января 2010

Может быть, вы могли бы сделать это таким образом, эта программа демонстрирует, как перехватить ошибку сегментации и выдает ее отладчику (это оригинальный код, используемый в AIX) и печатает трассировку стека до точки ошибки сегментации. Вам потребуется изменить переменную sprintf, чтобы использовать gdb в случае 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 */
}

Возможно, вам придется дополнительно добавить параметр, чтобы gdb выгрузил ядро, как показано здесь в этом блоге здесь .

16 голосов
/ 08 февраля 2012

Есть еще вещи, которые могут повлиять на генерацию дампа ядра. Я сталкивался с этим:

  • каталог для дампа должен быть доступен для записи. По умолчанию это текущий каталог процесса, но его можно изменить, установив /proc/sys/kernel/core_pattern.
  • в некоторых условиях значение ядра в /proc/sys/fs/suid_dumpable может помешать генерации ядра.

Есть еще ситуации, которые могут помешать генерации, которые описаны на странице руководства - попробуйте man core.

8 голосов
/ 02 марта 2016

для Ubuntu 14.04

  1. Проверьте, включен ли дамп ядра:

    ulimit -a
    
  2. Одна из строк должна быть:

    core file size          (blocks, -c) unlimited
    
  3. Если нет:

    gedit ~/.bashrc и добавьте ulimit -c unlimited в конец файла и сохраните, перезапустите терминал.

  4. Создайте приложение с отладочной информацией:

    В Makefile -O0 -g

  5. Запустить приложение, которое создает дамп ядра (файл дампов ядра с именем «core» должен быть создан рядом с файлом application_name):

    ./application_name
    
  6. Запустить под GDB:

    gdb application_name core
    
8 голосов
/ 19 октября 2012

Чтобы активировать дамп ядра, выполните следующие действия:

  1. В /etc/profile прокомментируйте строку:

    # ulimit -S -c 0 > /dev/null 2>&1
    
  2. В /etc/security/limits.conf закомментируйте строку:

    *               soft    core            0
    
  3. выполнить 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
    #
    
  4. чтобы проверить, записан ли файл core, вы можете уничтожить связанный процесс с помощью cmd kill -s SEGV <PID> (не нужно, на случай, если не записан файл core, это можно использовать как проверку):

    # kill -s SEGV <PID>
    

После записи файла core убедитесь, что снова отключили настройки coredump в соответствующих файлах (1./2./3.)!

4 голосов
/ 20 августа 2008

По умолчанию вы получите файл ядра. Убедитесь, что текущий каталог процесса доступен для записи, иначе файл ядра не будет создан.

1 голос
/ 24 августа 2018

Лучше включить программный дамп ядра с помощью системного вызова 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));
}
...