У меня есть процесс в Linux, который вызывает ошибку сегментации. Как я могу сказать, что он генерирует дамп ядра, когда он терпит неудачу?
Как создать дамп ядра в Linux при ошибке сегментации?
Ответ 1
Это зависит от того, какую оболочку вы используете. Если вы используете bash, то команда ulimit управляет несколькими настройками, относящимися к выполнению программы, например, нужно ли вы сбросить ядро. Если вы наберете
ulimit -c unlimited
то это сообщит bash, что его программы могут выгружать ядра любого размера. Вы можете указать такой размер, как 52M, а не неограниченно, если вы хотите, но на практике это не обязательно, поскольку размер основных файлов, вероятно, никогда не будет проблемой для вас.
В tcsh введите
limit coredumpsize unlimited
Ответ 2
Как объяснялось выше, реальный вопрос, задаваемый здесь, заключается в том, как включить дампы ядра в системе, где они не включены. На этот вопрос ответил.
Если вы пришли сюда, надеясь узнать, как создать основной дамп для зависания, ответ
gcore <pid>
если gcore недоступен в вашей системе, тогда
kill -ABRT <pid>
Не используйте kill -SEGV, поскольку это часто вызывает обработчик сигнала, что затрудняет диагностику застрявшего процесса
Ответ 3
То, что я сделал в конце, было прикрепление gdb к процессу, прежде чем он разбился, а затем, когда он получил segfault, я выполнил команду generate-core-file
. Это принудительное генерирование дампа ядра.
Ответ 4
Чтобы проверить, где генерируются дампы ядра, запустите:
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
сделать это неограниченным.
Затем проверьте снова, если дамп ядра успешен, вы увидите "(core dumped)" после индикации ошибки сегментации, как показано ниже:
Ошибка сегментации: 11 (ядро сброшено)
Смотрите также: ядро сброшено - но файл ядра не находится в текущем каталоге?
Ubuntu
В Ubuntu дампы ядра обрабатываются Apport и могут быть расположены в /var/crash/
. Однако он по умолчанию отключен в стабильных выпусках.
Для более подробной информации, пожалуйста, проверьте: Где я могу найти дамп ядра в Ubuntu? ,
Macos
Для macOS см.: Как создать дамп ядра в Mac OS X?
Ответ 5
Может быть, вы могли бы сделать это таким образом, эта программа демонстрирует, как перехватить ошибку сегментации и выдает ее отладчику (это оригинальный код, используемый в 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 сбросить ядро, как показано здесь, в этом блоге здесь.
Ответ 6
Есть больше вещей, которые могут повлиять на генерацию дампа ядра. Я столкнулся с ними:
- каталог для дампа должен быть доступен для записи. По умолчанию это текущий каталог процесса, но его можно изменить, установив
/proc/sys/kernel/core_pattern
. - в некоторых условиях значение ядра в
/proc/sys/fs/suid_dumpable
может помешать генерации ядра.
Есть больше ситуаций, которые могут помешать генерации, которые описаны на странице руководства - попробуйте man core
.
Ответ 7
Чтобы активировать дамп ядра, выполните следующие действия:
-
В
/etc/profile
прокомментируйте строку:# ulimit -S -c 0 > /dev/null 2>&1
-
В
/etc/security/limits.conf
закомментируйте строку:* soft core 0
-
выполните cmd
limit coredumpsize unlimited
и проверьте его с помощью 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 #
-
чтобы проверить, записывается ли файл corefile, вы можете убить связанный процесс с помощью cmd
kill -s SEGV <PID>
(не нужно, на всякий случай, если файл ядра не будет записан, это может использоваться как проверка):# kill -s SEGV <PID>
После того, как файл core был записан, обязательно отключите параметры coredump снова в связанных файлах (1./2./3.)!
Ответ 8
Для Ubuntu 14.04
-
Включить защитный дамп ядра:
ulimit -a
-
Одна из строк должна быть:
core file size (blocks, -c) unlimited
-
Если нет:
gedit ~/.bashrc
и добавьтеulimit -c unlimited
в конец файла и сохраните, запустите терминал. -
Создайте приложение с отладочной информацией:
В Makefile
-O0 -g
-
Запустить приложение, создающее ядро дампа (основной файл дампа с именем), должно быть создано около файла имени приложения):
./application_name
-
Запуск под gdb:
gdb application_name core
Ответ 9
По умолчанию вы получите основной файл. Убедитесь, что текущий каталог процесса доступен для записи, или не будет создан основной файл.
Ответ 10
Лучше включить программный дамп ядра, используя системный вызов 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));
}
Ответ 11
Подождите. Это автоматически делает. Не нужно это делать
Ответ 12
Стоит отметить, что если у вас настроен systemd, то все немного по-другому. Обычно в настройках файлы ядра core_pattern
посредством core_pattern
sysctl core_pattern
через systemd-coredump(8)
. Размер основного файла rlimit обычно уже настроен как "неограниченный".
Затем можно получить дампы ядра с помощью coredumpctl(1)
.
Хранение дампов ядра и т.д. Настраивается с помощью coredump.conf(5)
. Есть примеры того, как получить файлы ядра на странице руководства coredumpctl, но вкратце это будет выглядеть так:
Найдите основной файл:
[[email protected]]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET 16163 1224 1224 11 present /home/vps/test_me
Получить основной файл:
[[email protected]]~$ coredumpctl -o test_me.core dump 16163