Comment générer un dump de noyau sous Linux quand un processus a un défaut de segmentation?

J'ai un processus sous Linux qui a un problème de segmentation. Comment puis-je lui dire de générer un dump core quand il échoue?

181
demandé sur Mark Harrison 2008-08-20 17:38:14

10 réponses

Cela dépend du shell que vous utilisez. Si vous utilisez bash, alors la commande ulimit contrôle plusieurs paramètres relatifs à l'exécution du programme, par exemple si vous devez vider core. Si vous tapez

ulimit -c unlimited

alors cela indiquera à bash que ses programmes peuvent décharger des noyaux de n'importe quelle taille. Vous pouvez spécifier une taille telle que 52M au lieu de illimité si vous voulez, mais en pratique cela ne devrait pas être nécessaire puisque la taille des fichiers core ne sera probablement jamais un question pour vous.

dans tcsh, tapez

limit coredumpsize unlimited
216
répondu Eli Courtwright 2008-11-17 22:22:13

comme expliqué ci-dessus, la vraie question qui se pose ici est de savoir comment activer les dumps core sur un système où ils ne sont pas activés. La réponse à cette question est donnée ici.

si vous êtes venu ici dans l'espoir d'apprendre à générer un dump core pour un processus hung, la réponse est

gcore <pid>

si gcoré n'est pas disponible sur votre système alors

kill -ABRT <pid>

N'utilisez pas kill-SEGV car cela fera souvent appel à un gestionnaire de signal faisant il est plus difficile à diagnostiquer l'coincé processus de

46
répondu George Colpitts 2016-09-22 20:51:05

ce que j'ai fait à la fin était d'attacher gdb au processus avant qu'il ne s'écrase, et puis quand il a obtenu le segfault j'ai exécuté la commande generate-core-file . Cette génération forcée d'une décharge de noyau.

22
répondu Nathan Fellman 2010-01-26 13:33:27

peut-être que vous pourriez le faire de cette façon, ce programme est une démonstration de la façon de piéger un défaut de segmentation et de shells out à un débogueur (c'est le code original utilisé sous AIX ) et imprime la trace de pile jusqu'au point d'un défaut de segmentation. Vous devrez changer la variable sprintf pour utiliser gdb dans le cas 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 */
}

vous pourriez avoir à ajouter un paramètre pour obtenir gdb pour Dumper le noyau comme montré ici blog ici .

19
répondu t0mm13b 2016-10-19 06:50:41

pour vérifier où les dumps du cœur sont générés, exécutez:

sysctl kernel.core_pattern

%e est le nom du procédé et %t le temps du système. Vous pouvez le modifier dans /etc/sysctl.conf et recharger par sysctl -p .

si les fichiers de base ne sont pas générés (tester par: sleep 10 & et killall -SIGSEGV sleep ), vérifier les limites par: ulimit -a .

si la taille de votre fichier de base est limitée, Lancez:

ulimit -c unlimited

pour le rendre illimité.

puis tester à nouveau, si le dumping du cœur est réussi, vous verrez "(core dumped) "après l'indication de défaut de segmentation comme ci-dessous:

segmentation fault: 11 (core dumped)


Ubuntu

dans Ubuntu généralement les dumps sont traitées par apport dans /var/crash/ , mais dans un format différent, cependant il n'est pas activé par défaut dans les versions stables. Lire plus à Ubuntu wiki .

il utilise core_pattern pour Piper directement le noyau dump dans l'apport:

$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c

donc même les fichiers de base sont désactivés par ulimit , apport captureront toujours le crash ( comment activer ou désactiver L'Apport? ).


macOS

pour macOS, voir: Comment générer des core dumps dans Mac OS X?

17
répondu kenorb 2017-12-19 00:40:26

il y a plus de choses qui peuvent influencer la génération d'un noyau dump. J'ai rencontré ceci:

  • le répertoire du dump doit être accessible en écriture. Par défaut c'est le répertoire courant du processus, mais qui peut être modifiée par le paramètre /proc/sys/kernel/core_pattern .
  • dans certaines conditions, la valeur du noyau dans /proc/sys/fs/suid_dumpable peut empêcher le noyau d'être généré.

il y a plus de situations qui peuvent empêchez la génération qui sont décrites dans la page de manuel - essayez man core .

15
répondu mlutescu 2012-02-08 10:31:21

pour activer le vidage du cœur, faire ce qui suit:

  1. Dans /etc/profile commentaire de la ligne:

    # ulimit -S -c 0 > /dev/null 2>&1
    
  2. Dans /etc/security/limits.conf en commentaire la ligne:

    *               soft    core            0
    
  3. exécuter le cmd limit coredumpsize unlimited et le vérifier avec le 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. pour vérifier si la corefile obtient écrit Vous pouvez tuer le processus relatif avec cmd kill -s SEGV <PID> (ne devrait pas être nécessaire, juste au cas où aucun fichier de base obtient écrit cela peut être utilisé comme un chèque):

    # kill -s SEGV <PID>
    

une fois le corefile écrit, assurez-vous de désactiver à nouveau les paramètres de coredump dans les fichiers correspondants (1./2./ 3.) !

8
répondu Edgar Jordi 2017-04-05 17:29:47

Pour Ubuntu 14.04

  1. Vérifier core dump activé:

    ulimit -a
    
  2. L'une des lignes devrait être:

    core file size          (blocks, -c) unlimited
    
  3. Si ce n' :

    gedit ~/.bashrc et ajouter ulimit -c unlimited à la fin du fichier et enregistrer, relancer le terminal.

  4. Construisez votre application avec les informations de débogage :

    Dans Le Makefile -O0 -g

  5. exécuter l'application qui crée le dump de base (le fichier de dump de base avec le nom' core’ doit être créé près du fichier application_name):

    ./application_name
    
  6. Exécuter sous gdb:

    gdb application_name core
    
7
répondu mrgloom 2018-01-25 17:17:30

Par défaut, vous obtiendrez un fichier core. Vérifiez que le répertoire courant du processus est accessible en écriture, ou pas de fichier de base sera créée.

4
répondu Mark Harrison 2008-08-20 14:38:36

il est préférable d'activer le dump core par programmation en utilisant l'appel système setrlimit .

exemple:

#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));
}
0
répondu kgbook 2018-08-24 08:52:59