¿Cómo generar un volcado de núcleo en Linux en una falla de segmentación?


Respuestas:


249

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

21
@lzprgmr: Para aclarar: la razón por la cual los volcados de núcleo no se generan de forma predeterminada es que el límite no se establece y / o se establece en 0, lo que evita que el núcleo sea volcado. Al establecer un límite ilimitado, garantizamos que siempre se puedan generar volcados de núcleo.
Eli Courtwright

66
Este enlace va más profundo y ofrece más opciones para permitir la generación de volcados de núcleo en Linux. El único inconveniente es que algunos comandos / configuraciones no se explican.
Salsa

66
En bash 4.1.2 (1), no se pueden especificar límites de liberación como 52M, lo que da como resultado un mensaje de error de número no válido. La página del manual dice que "los valores están en incrementos de 1024 bytes".
a1an

44
Bueno, tuve un proyecto "pequeño" de OpenGL, que una vez hizo algo extraño y causó el bloqueo del servidor X. Cuando volví a iniciar sesión, vi un pequeño y lindo archivo central de 17 GB (en una partición de 25 GB). Definitivamente es una buena idea mantener limitado el tamaño del archivo principal :)
IceCool

1
@PolarisUser: si desea asegurarse de que su partición no se coma, le recomiendo establecer un límite de algo como 1 concierto. Eso debería ser lo suficientemente grande como para manejar cualquier volcado de núcleo razonable, sin amenazar con usar todo el espacio restante en el disco duro.
Eli Courtwright

60

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


Creo que es mucho más probable que -ABRTinvoque 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.
Celticminstrel

32

Para verificar dónde se generan los volcados de núcleo, ejecute:

sysctl kernel.core_pattern

o:

cat /proc/sys/kernel/core_pattern

donde %eestá el nombre del proceso y %tla hora del sistema. Puedes cambiarlo /etc/sysctl.confy 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?


Ubuntu

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? .

Mac OS

Para macOS, consulte: ¿Cómo generar volcados de núcleo en Mac OS X?


3
Para Ubuntu, para volver rápidamente al comportamiento normal (volcar un archivo central en el directorio actual), simplemente detenga el servicio apport con "sudo service apport stop". También tenga en cuenta que si está ejecutando dentro de Docker, esa configuración se controla en el sistema host y no dentro del contenedor.
Digicrat

26

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-filecomando. Esa generación forzada de un basurero.


¿Cómo adjuntaste gdb al proceso?
Chani

66
Para responder a Ritwik G, para adjuntar un proceso a gdb, simplemente inicie gdb e ingrese 'attach <pid>' donde <pid> es el número pid del proceso que desea adjuntar.
Jean-Dominique Frattini

(abreviado como ge)
user202729

Si tienen una nueva pregunta, deben hacer una nueva pregunta en lugar de hacer un comentario.
user202729

Lo extraño es que ya se estableció ulimit -ca unlimited, pero el archivo de núcleo se calma sin creado, el generate-core-filearchivo de sesión de GDB hace crear el archivo central, gracias.
CodyChan

19

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 sprintfvariable a utilizar gdben 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í .


16

Hay más cosas que pueden influir en la generación de un volcado de núcleo. Encontré estos:

  • el directorio para el volcado debe poder escribirse. De manera predeterminada, este es el directorio actual del proceso, pero puede modificarse mediante la configuración /proc/sys/kernel/core_pattern.
  • en algunas condiciones, el valor del núcleo /proc/sys/fs/suid_dumpablepuede 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.


9

Para activar el volcado del núcleo, haga lo siguiente:

  1. En /etc/profilecomentario la línea:

    # ulimit -S -c 0 > /dev/null 2>&1
  2. En /etc/security/limits.confcomentar la línea:

    *               soft    core            0
  3. ejecute el cmd limit coredumpsize unlimitedy 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
    #
  4. 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.).


9

Para Ubuntu 14.04

  1. Verifique el volcado del núcleo habilitado:

    ulimit -a
  2. Una de las líneas debería ser:

    core file size          (blocks, -c) unlimited
  3. Si no :

    gedit ~/.bashrcy agregue ulimit -c unlimitedal final del archivo y guarde, vuelva a ejecutar el terminal.

  4. Cree su aplicación con información de depuración:

    En Makefile -O0 -g

  5. 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
  6. Ejecutar bajo gdb:

    gdb application_name core

En el Paso 3, ¿Cómo 'volver a ejecutar' el terminal? ¿Te refieres a reiniciar?
Naveen

@Naveen no, solo cierra el terminal y abre uno nuevo, también parece que puedes poner el ulimit -c unlimitedterminal para una solución temporal, porque solo la edición ~/.bashrcrequiere que se reinicie el terminal para que los cambios surtan efecto.
mrgloom

4

Por defecto obtendrá un archivo central. Verifique que el directorio actual del proceso sea editable o que no se creará ningún archivo central.


44
Por "directorio actual del proceso", ¿quiere decir $ cwd en el momento en que se ejecutó el proceso? ~ / abc> / usr / bin / cat def si cat se bloquea, ¿es el directorio actual en cuestión ~ / abc o / usr / bin?
Nathan Fellman el

55
~ / abc. ¡Hmm, los comentarios deben tener 15 caracteres!
Mark Harrison

55
Este sería el directorio actual en el momento de la SEGV. Además, los procesos que se ejecutan con un usuario y / o grupo efectivo diferente al del usuario / grupo real no escribirán archivos principales.
Darron

2

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));
}

¿Por qué es eso mejor?
Nathan Fellman

archivo principal generado después del bloqueo, no es necesario ulimit -c unlimiteden el entorno de línea de comandos y luego vuelve a ejecutar la aplicación.
kgbook

No quiero un volcado de núcleo cada vez que se bloquea, solo cuando un usuario se contacta conmigo como desarrollador para verlo. Si se bloquea 100 veces, no necesito 100 volcados de núcleo para mirar.
Nathan Fellman

En ese caso, mejor usar ulimit -c unlimited. También puede compilar con la definición de marco, la aplicación no incluirá el enable_core_dumpsí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.
kgbook

incluso si está calificado por una macro, eso todavía requiere que vuelva a compilar si quiero generar un volcado de núcleo, en lugar de simplemente ejecutar un comando en el shell antes de volver a ejecutarlo.
Nathan Fellman

1

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_patternvalor 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

0

Ubuntu 19.04

Todas las otras respuestas en sí mismas no me ayudaron. Pero el siguiente resumen hizo el trabajo

Crea ~/.config/apport/settingscon 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:

  • Algunas respuestas sugieren cambiar core_pattern. Tenga en cuenta que el archivo puede sobrescribir ese archivo al reiniciarlo.
  • Simplemente detener la distribución no hizo el trabajo
  • El ulimit -cvalor 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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.