Tengo un proceso en Linux que tiene un error de segmentación. ¿Cómo puedo decirle que genere un volcado de núcleo cuando falla?
Tengo un proceso en Linux que tiene un error de segmentación. ¿Cómo puedo decirle que genere un volcado de núcleo cuando falla?
Respuestas:
Esto depende de qué shell está utilizando. Si está utilizando bash, el comando ulimit controla varias configuraciones relacionadas con la ejecución del programa, como por ejemplo si debe volcar el núcleo. Si escribes
ulimit -c unlimited
entonces eso le dirá a bash que sus programas pueden volcar núcleos de cualquier tamaño. Puede especificar un tamaño como 52M en lugar de ilimitado si lo desea, pero en la práctica esto no debería ser necesario ya que el tamaño de los archivos principales probablemente nunca será un problema para usted.
En tcsh, escribirías
limit coredumpsize unlimited
Como se explicó anteriormente, la verdadera pregunta que se hace aquí es cómo habilitar los volcados de núcleo en un sistema donde no están habilitados. Esa pregunta se responde aquí.
Si ha venido aquí esperando aprender cómo generar un volcado de núcleo para un proceso bloqueado, la respuesta es
gcore <pid>
si gcore no está disponible en su sistema, entonces
kill -ABRT <pid>
No use kill -SEGV ya que a menudo invocará un controlador de señal que dificultará el diagnóstico del proceso atascado
-ABRT
invoque un controlador de señal que -SEGV
, ya que un aborto es más probable que sea recuperable que un segfault. (Si maneja un segfault, normalmente se activará nuevamente tan pronto como su manejador salga). Una mejor opción de señal para generar un volcado de núcleo es -QUIT
.
Para verificar dónde se generan los volcados de núcleo, ejecute:
sysctl kernel.core_pattern
o:
cat /proc/sys/kernel/core_pattern
donde %e
está el nombre del proceso y %t
la hora del sistema. Puedes cambiarlo /etc/sysctl.conf
y recargarlo sysctl -p
.
Si los archivos del núcleo no se generan (prueba por: sleep 10 &
e killall -SIGSEGV sleep
), comprobar los límites de: ulimit -a
.
Si el tamaño del archivo principal es limitado, ejecute:
ulimit -c unlimited
para hacerlo ilimitado.
Luego pruebe nuevamente, si el volcado del núcleo es exitoso, verá "(núcleo volcado)" después de la indicación de falla de segmentación como se muestra a continuación:
Falla de segmentación: 11 (núcleo descargado)
Ver también: núcleo volcado, pero ¿el archivo central no está en el directorio actual?
En Ubuntu, los volcados del núcleo son manejados por Apport y pueden ubicarse en /var/crash/
. Sin embargo, está deshabilitado de forma predeterminada en las versiones estables.
Para obtener más detalles, consulte: ¿Dónde encuentro el volcado del núcleo en Ubuntu? .
Para macOS, consulte: ¿Cómo generar volcados de núcleo en Mac OS X?
Lo que hice al final fue adjuntar gdb al proceso antes de que se bloqueara, y luego, cuando obtuvo la segfault, ejecuté el generate-core-file
comando. Esa generación forzada de un basurero.
ge
)
ulimit -c
a unlimited
, pero el archivo de núcleo se calma sin creado, el generate-core-file
archivo de sesión de GDB hace crear el archivo central, gracias.
Tal vez podría hacerlo de esta manera, este programa es una demostración de cómo atrapar un error de segmentación y se distribuye a un depurador (este es el código original utilizado AIX
) e imprime el seguimiento de la pila hasta el punto de un error de segmentación. Deberá cambiar la sprintf
variable a utilizar gdb
en el caso de 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 */
}
Es posible que deba agregar un parámetro adicional para que gdb descargue el núcleo como se muestra aquí en este blog aquí .
Hay más cosas que pueden influir en la generación de un volcado de núcleo. Encontré estos:
/proc/sys/kernel/core_pattern
. /proc/sys/fs/suid_dumpable
puede impedir que se genere el núcleo.Hay más situaciones que pueden evitar la generación que se describen en la página del manual: intente man core
.
Para activar el volcado del núcleo, haga lo siguiente:
En /etc/profile
comentario la línea:
# ulimit -S -c 0 > /dev/null 2>&1
En /etc/security/limits.conf
comentar la línea:
* soft core 0
ejecute el cmd limit coredumpsize unlimited
y verifíquelo con 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
#
para verificar si el archivo core se escribe, puede eliminar el proceso relacionado con cmd kill -s SEGV <PID>
(no debería ser necesario, en caso de que no se escriba ningún archivo core, esto puede usarse como un control):
# kill -s SEGV <PID>
Una vez que se haya escrito el archivo core, asegúrese de volver a desactivar la configuración de coredump en los archivos relacionados (1./2./3.).
Para Ubuntu 14.04
Verifique el volcado del núcleo habilitado:
ulimit -a
Una de las líneas debería ser:
core file size (blocks, -c) unlimited
Si no :
gedit ~/.bashrc
y agregue ulimit -c unlimited
al final del archivo y guarde, vuelva a ejecutar el terminal.
Cree su aplicación con información de depuración:
En Makefile -O0 -g
Ejecute la aplicación que crea el volcado del núcleo (el archivo de volcado del núcleo con el nombre 'core' debe crearse cerca del archivo nombre_aplicación):
./application_name
Ejecutar bajo gdb:
gdb application_name core
ulimit -c unlimited
terminal para una solución temporal, porque solo la edición ~/.bashrc
requiere que se reinicie el terminal para que los cambios surtan efecto.
Por defecto obtendrá un archivo central. Verifique que el directorio actual del proceso sea editable o que no se creará ningún archivo central.
Es mejor activar el volcado del núcleo mediante programación mediante la llamada al sistema setrlimit
.
ejemplo:
#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
en el entorno de línea de comandos y luego vuelve a ejecutar la aplicación.
ulimit -c unlimited
. También puede compilar con la definición de marco, la aplicación no incluirá el enable_core_dump
símbolo si no define esa macro cuando se lance, y obtendrá un reemplazo de volcado de núcleo con la versión de depuración.
Vale la pena mencionar que si usted tiene un systemd puesta en marcha, entonces las cosas son un poco diferentes bits. La configuración normalmente haría que los archivos principales se canalizaran, mediante el core_pattern
valor sysctl, a través systemd-coredump(8)
. El tamaño del archivo central rlimit normalmente ya estaría configurado como "ilimitado".
Entonces es posible recuperar los volcados de núcleo utilizando coredumpctl(1)
.
El almacenamiento de los volcados de núcleo, etc. está configurado por coredump.conf(5)
. Hay ejemplos de cómo obtener los archivos principales en la página de manual de coredumpctl, pero en resumen, se vería así:
Encuentra el archivo principal:
[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
Obtenga el archivo central:
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
Todas las otras respuestas en sí mismas no me ayudaron. Pero el siguiente resumen hizo el trabajo
Crea ~/.config/apport/settings
con el siguiente contenido:
[main]
unpackaged=true
(Esto le dice a apport que también escriba volcados de núcleo para aplicaciones personalizadas)
comprobar: ulimit -c
. Si genera 0, corríjalo con
ulimit -c unlimited
Por si acaso reiniciar apport:
sudo systemctl restart apport
Los archivos de bloqueo ahora están escritos /var/crash/
. Pero no puedes usarlos con gdb. Para usarlos con gdb, use
apport-unpack <location_of_report> <target_directory>
Más información:
core_pattern
. Tenga en cuenta que el archivo puede sobrescribir ese archivo al reiniciarlo.ulimit -c
valor puede cambiar automáticamente mientras intenta otras respuestas de la web. Asegúrese de verificarlo regularmente durante la configuración de su creación de volcado de memoria.Referencias