У мене в Linux процес, який отримує помилку в сегментації. Як я можу сказати, що він генерує основний дамп, коли він не працює?
У мене в Linux процес, який отримує помилку в сегментації. Як я можу сказати, що він генерує основний дамп, коли він не працює?
Відповіді:
Це залежить від того, яку оболонку ви використовуєте. Якщо ви використовуєте bash, то команда ulimit керує кількома налаштуваннями, що стосуються виконання програми, наприклад, чи слід скидати ядро. Якщо ви введете
ulimit -c unlimited
тоді це скаже bash, що його програми можуть скидати ядра будь-якого розміру. Ви можете вказати розмір, наприклад, 52M замість необмеженого, якщо хочете, але на практиці це не повинно бути необхідним, оскільки розмір основних файлів, ймовірно, ніколи не буде проблемою для вас.
В tcsh ви введете
limit coredumpsize unlimited
Як було пояснено вище, тут задається справжнє питання, як увімкнути основні скиди в системі, де вони не включені. На це питання тут відповіли.
Якщо ви приїхали сюди, сподіваючись навчитися генерувати основний дамп для вивішеного процесу, відповідь така
gcore <pid>
якщо gcore недоступний у вашій системі,
kill -ABRT <pid>
Не використовуйте kill -SEGV, оскільки це часто викликає обробник сигналу, що ускладнює діагностику застрялого процесу
-ABRT
буде викликано обробник сигналу, ніж -SEGV
, оскільки аборт швидше підлягає відновленню, ніж сегмент за замовчуванням. (Якщо ви обробляєте segfault, звичайно, він буде спрацьовувати знову, як тільки ваш обробник вийде.) Кращий вибір сигналу для генерації дампів ядра -QUIT
.
Щоб перевірити, де створені основні скиди, запустіть:
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 (скидається ядро)
Дивитися також: core dumped - але основний файл відсутній у поточному каталозі?
У Ubuntu основними дампами обробляються Apport і вони можуть бути розміщені в/var/crash/
. Однак він стабільно вимкнено за умовчанням.
Для отримання більш детальної інформації, будь ласка, перевірте: Де я можу знайти основний дамп в Ubuntu?.
Про macOS дивіться у розділі: Як генерувати основні скиди в Mac OS X?
Що я зробив наприкінці, це приєднати gdb до процесу перед тим, як він вийшов з ладу, а потім, коли він отримав сегмент за замовчуванням, я виконав generate-core-file
команду. Це вимушене покоління основного сміття.
ge
)
ulimit -c
на unlimited
, але файл ядра заспокоєний не створений, generate-core-file
файл в GdB сесії дійсно створює файл ядра, спасибі.
Можливо, ви могли це зробити так, ця програма - демонстрація того, як захопити помилку сегментації та виводить на налагоджувач (це оригінальний код, який використовується під 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 скинути ядро , як показано тут , в цьому блозі тут .
Є більше речей, які можуть впливати на генерацію основного сміттєзвалища. Я стикався з цими:
/proc/sys/kernel/core_pattern
. /proc/sys/fs/suid_dumpable
може перешкоджати генеруванню ядра.Існує більше ситуацій, які можуть перешкоджати поколінню, описаному на сторінці man - спробуйте man core
.
Для того, щоб активувати основний дамп, виконайте наступне:
У /etc/profile
коментарі рядок:
# ulimit -S -c 0 > /dev/null 2>&1
У /etc/security/limits.conf
коментарі з рядка:
* soft core 0
виконати 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
#
щоб перевірити, чи не написано corefile, ви можете вбити відповідний процес за допомогою cmd kill -s SEGV <PID>
(це не потрібно, на випадок, якщо жоден основний файл не буде записаний, це може бути використане як перевірка):
# kill -s SEGV <PID>
Після того, як основний файл буде записаний, переконайтеся, що знову відключити настройки coredump у відповідних файлах (1./2./3.)!
Для Ubuntu 14.04
Перевірити активований базовий дамп:
ulimit -a
Один з рядків повинен бути:
core file size (blocks, -c) unlimited
Якщо ні :
gedit ~/.bashrc
і додати ulimit -c unlimited
до кінця файлу та зберегти, запустити термінал.
Створіть свою програму з інформацією про налагодження:
У Makefile -O0 -g
Запустіть програму, яка створює основний дамп (основний дамп-файл із назвою 'core' повинен бути створений поруч з файлом application_name):
./application_name
Запустити під gdb:
gdb application_name core
ulimit -c unlimited
термінал для тимчасового рішення, тому що лише для редагування ~/.bashrc
потрібен обмеження терміналу для змін.
За замовчуванням ви отримаєте основний файл. Переконайтеся, що поточний каталог процесу записується чи не буде створено основний файл.
Краще включити основний дамп програмно за допомогою системного виклику 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));
}
ulimit -c unlimited
в середовищі командного рядка, а потім повторно запускати програму.
ulimit -c unlimited
. Крім того, ви можете компілювати з визначенням marco, додаток не буде містити enable_core_dump
символ, якщо не визначити цей макрос при випуску, і ви отримаєте основний дамп замінити на версію налагодження.
Варто відзначити , що якщо у вас є Systemd набір вгору, то речі трохи по- іншому. Як правило, у налаштованому режимі основні файли будуть прокладені через core_pattern
значення sysctl черезsystemd-coredump(8)
. Зазвичай розмір файлу rlimit зазвичай налаштовується як "необмежений".
Потім можна отримати основні відвали за допомогою coredumpctl(1)
.
Зберігання основних звалищ тощо налаштовано coredump.conf(5)
. Є приклади того, як отримати основні файли на сторінці користувача coredumpctl, але коротше, це виглядатиме так:
Знайдіть основний файл:
[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET 16163 1224 1224 11 present /home/vps/test_me
Отримайте основний файл:
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
Усі інші відповіді самі мені не допомогли. Але наступна підсумка зробила роботу
Створіть ~/.config/apport/settings
із наступним вмістом:
[main]
unpackaged=true
(Це повідомляє про можливість також писати основні скиди для спеціальних додатків)
перевірити: ulimit -c
. Якщо він виводить 0, зафіксуйте його
ulimit -c unlimited
Про всяк випадок, якщо перезапустити приклад:
sudo systemctl restart apport
Файли збоїв тепер записані в /var/crash/
. Але ви не можете використовувати їх з gdb. Щоб використовувати їх з gdb, використовуйте
apport-unpack <location_of_report> <target_directory>
Додаткова інформація:
core_pattern
. Пам’ятайте, що цей файл може перезаписатися службою apport при перезапуску.ulimit -c
Значення може переодягнутися автоматично в той час як ви намагаєтеся інші відповіді в Інтернеті. Не забудьте регулярно перевіряти це під час налаштування вашого основного дампського створення.Список літератури: