Ich habe einen Prozess unter Linux, bei dem ein Segmentierungsfehler auftritt. Wie kann ich ihm sagen, dass er einen Core-Dump generieren soll, wenn er fehlschlägt?
Ich habe einen Prozess unter Linux, bei dem ein Segmentierungsfehler auftritt. Wie kann ich ihm sagen, dass er einen Core-Dump generieren soll, wenn er fehlschlägt?
Antworten:
Dies hängt davon ab, welche Shell Sie verwenden. Wenn Sie bash verwenden, steuert der Befehl ulimit verschiedene Einstellungen in Bezug auf die Programmausführung, z. B. ob Sie den Core sichern sollten. Wenn Sie tippen
ulimit -c unlimited
dann wird das bash sagen, dass seine Programme Kerne jeder Größe ausgeben können. Sie können eine Größe wie 52 MB anstelle von unbegrenzt angeben, wenn Sie möchten. In der Praxis sollte dies jedoch nicht erforderlich sein, da die Größe der Kerndateien für Sie wahrscheinlich nie ein Problem darstellt.
In tcsh würden Sie eingeben
limit coredumpsize unlimited
Wie oben erläutert, wird hier die eigentliche Frage gestellt, wie Core Dumps auf einem System aktiviert werden können, auf dem sie nicht aktiviert sind. Diese Frage wird hier beantwortet.
Wenn Sie hierher gekommen sind, um zu erfahren, wie Sie einen Core-Dump für einen blockierten Prozess generieren, lautet die Antwort
gcore <pid>
Wenn gcore auf Ihrem System nicht verfügbar ist, dann
kill -ABRT <pid>
Verwenden Sie kill -SEGV nicht, da dies häufig einen Signalhandler aufruft, der die Diagnose des festgefahrenen Prozesses erschwert
-ABRT
ein Signal-Handler -SEGV
aufgerufen wird als , da ein Abbruch eher wiederherstellbar ist als ein Segfault. (Wenn Sie einen Segfault behandeln, wird dieser normalerweise erst wieder ausgelöst, sobald Ihr Handler beendet wird.) Eine bessere Signalauswahl für die Erzeugung eines Core-Dumps ist -QUIT
.
Führen Sie Folgendes aus, um zu überprüfen, wo die Core-Dumps generiert werden:
sysctl kernel.core_pattern
oder:
cat /proc/sys/kernel/core_pattern
Wo %e
ist der Prozessname und %t
die Systemzeit. Sie können es ändern /etc/sysctl.conf
und neu laden durch sysctl -p
.
Wenn die Kerndateien nicht generiert werden (testen Sie sie mit: sleep 10 &
und killall -SIGSEGV sleep
), überprüfen Sie die Grenzwerte mit : ulimit -a
.
Wenn Ihre Kerndateigröße begrenzt ist, führen Sie Folgendes aus:
ulimit -c unlimited
um es unbegrenzt zu machen.
Testen Sie dann erneut, ob das Core-Dumping erfolgreich ist. Nach der Anzeige des Segmentierungsfehlers wird "(Core-Dumping)" angezeigt:
Segmentierungsfehler: 11 (Core Dumped)
Siehe auch: Core Dumped - aber Core-Datei befindet sich nicht im aktuellen Verzeichnis?
In Ubuntu werden die Core-Dumps von Apport verwaltet und können sich in befinden /var/crash/
. In stabilen Releases ist es jedoch standardmäßig deaktiviert.
Weitere Informationen finden Sie unter: Wo finde ich den Core Dump in Ubuntu? .
Informationen zu macOS finden Sie unter: Wie werden Core-Dumps in Mac OS X generiert?
Was ich am Ende getan habe, war, gdb an den Prozess anzuhängen, bevor er abstürzte, und dann, als er den Segfault bekam, habe ich den generate-core-file
Befehl ausgeführt. Diese erzwungene Erzeugung eines Kerndumps.
ge
)
ulimit -c
habe unlimited
, aber die Kerndatei ist noch nicht erstellt, die generate-core-file
Datei in der GDB-Sitzung erstellt die Kerndatei, danke.
Vielleicht könnten Sie es auf diese Weise tun. Dieses Programm ist eine Demonstration, wie ein Segmentierungsfehler abgefangen und an einen Debugger weitergeleitet wird (dies ist der ursprüngliche Code, der unter verwendet wird AIX
), und druckt die Stapelverfolgung bis zum Punkt eines Segmentierungsfehlers. Sie müssen die sprintf
Variable ändern, die gdb
im Fall von Linux verwendet werden soll.
#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 */
}
Möglicherweise müssen Sie zusätzlich einen Parameter hinzufügen, damit gdb den Kern entleert, wie hier in diesem Blog hier gezeigt .
Es gibt weitere Faktoren, die die Erzeugung eines Core-Dumps beeinflussen können. Ich bin auf Folgendes gestoßen:
/proc/sys/kernel/core_pattern
. /proc/sys/fs/suid_dumpable
verhindern, dass der Kern generiert wird.Es gibt weitere Situationen, die die in der Manpage beschriebene Generierung verhindern können man core
.
Gehen Sie wie folgt vor, um den Core Dump zu aktivieren:
Im /etc/profile
Kommentar der Zeile:
# ulimit -S -c 0 > /dev/null 2>&1
Im /etc/security/limits.conf
Kommentar aus der Zeile:
* soft core 0
Führen Sie das cmd aus limit coredumpsize unlimited
und überprüfen Sie es mit 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
#
Um zu überprüfen, ob die Core-Datei geschrieben wird, können Sie den zugehörigen Prozess mit cmd beenden kill -s SEGV <PID>
(sollte nicht benötigt werden, nur für den Fall, dass keine Core-Datei geschrieben wird, kann dies als Überprüfung verwendet werden):
# kill -s SEGV <PID>
Nachdem die Corefile geschrieben wurde, müssen Sie die Coredump-Einstellungen in den zugehörigen Dateien (1./2./3.) Wieder deaktivieren!
Für Ubuntu 14.04
Überprüfen Sie, ob der Core Dump aktiviert ist:
ulimit -a
Eine der Zeilen sollte sein:
core file size (blocks, -c) unlimited
Wenn nicht :
gedit ~/.bashrc
und ulimit -c unlimited
am Ende der Datei hinzufügen und speichern, Terminal erneut ausführen.
Erstellen Sie Ihre Anwendung mit Debug-Informationen:
In Makefile -O0 -g
Führen Sie eine Anwendung aus, die einen Core-Dump erstellt (Core-Dump-Datei mit dem Namen 'core' sollte in der Nähe der Datei application_name erstellt werden):
./application_name
Unter gdb ausführen:
gdb application_name core
ulimit -c unlimited
Terminal auch nur für eine temporäre Lösung ~/.bashrc
einfügen , da nur für die Bearbeitung ein Neustart des Terminals erforderlich ist, damit Änderungen wirksam werden.
Standardmäßig erhalten Sie eine Kerndatei. Überprüfen Sie, ob das aktuelle Verzeichnis des Prozesses beschreibbar ist oder keine Kerndatei erstellt wird.
Es ist besser, den Core Dump mithilfe eines Systemaufrufs programmgesteuert einzuschalten setrlimit
.
Beispiel:
#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
in der Befehlszeilenumgebung, und dann die Anwendung erneut ausführen.
ulimit -c unlimited
. Sie können auch mit marco definition kompilieren. Die Anwendung enthält kein enable_core_dump
Symbol, wenn dieses Makro bei der Veröffentlichung nicht definiert wird, und Sie erhalten einen Core-Dump, der durch die Debug-Version ersetzt wird.
Es ist erwähnenswert, dass, wenn Sie ein System eingerichtet haben, die Dinge ein bisschen anders sind. Bei der Einrichtung werden die Kerndateien normalerweise mithilfe des core_pattern
sysctl-Werts durchgeleitet systemd-coredump(8)
. Die Kerndateigröße rlimit wird normalerweise bereits als "unbegrenzt" konfiguriert.
Es ist dann möglich, die Core-Dumps mit abzurufen coredumpctl(1)
.
Die Speicherung von Core Dumps usw. wird von konfiguriert coredump.conf(5)
. Es gibt Beispiele, wie Sie die Kerndateien in der Manpage coredumpctl abrufen können, aber kurz gesagt würde es so aussehen:
Suchen Sie die Kerndatei:
[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
Holen Sie sich die Kerndatei:
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
Alle anderen Antworten selbst haben mir nicht geholfen. Aber die folgende Zusammenfassung hat den Job gemacht
Erstellen Sie ~/.config/apport/settings
mit folgendem Inhalt:
[main]
unpackaged=true
(Dies weist Apport an, auch Core-Dumps für benutzerdefinierte Apps zu schreiben.)
überprüfen : ulimit -c
. Wenn es 0 ausgibt, beheben Sie es mit
ulimit -c unlimited
Nur für den Fall, dass Apport neu gestartet wird:
sudo systemctl restart apport
Absturzdateien werden jetzt geschrieben /var/crash/
. Sie können sie jedoch nicht mit gdb verwenden. Um sie mit gdb zu verwenden, verwenden Sie
apport-unpack <location_of_report> <target_directory>
Weitere Informationen:
core_pattern
. Beachten Sie, dass diese Datei beim Neustart möglicherweise vom Apport-Dienst überschrieben wird.ulimit -c
Wert wird möglicherweise automatisch geändert, wenn Sie andere Antworten im Web ausprobieren. Überprüfen Sie dies regelmäßig, während Sie die Erstellung Ihres Core-Dumps einrichten.Verweise: