Question

J'ai un processus sous Linux qui rencontre une erreur de segmentation.Comment puis-je lui dire de générer un core dump en cas d'échec ?

Était-ce utile?

La solution

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

ulimit -c unlimited

alors cela indiquera à bash que ses programmes peuvent vider des cœurs de n'importe quelle taille.Vous pouvez spécifier une taille telle que 52 Mo au lieu d'illimitée si vous le souhaitez, mais en pratique, cela ne devrait pas être nécessaire puisque la taille des fichiers principaux ne sera probablement jamais un problème pour vous.

En tcsh, tu taperais

limit coredumpsize unlimited

Autres conseils

Comme expliqué ci-dessus, la vraie question posée ici est de savoir comment activer les core dumps sur un système où ils ne sont pas activés.Cette question trouve une réponse ici.

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

gcore <pid>

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

kill -ABRT <pid>

N'utilisez pas kill -SEGV car cela invoquera souvent un gestionnaire de signal, ce qui rendra plus difficile le diagnostic du processus bloqué.

Ce que j'ai fait à la fin, c'est d'attacher gdb au processus avant qu'il ne plante, puis quand il a eu l'erreur de segmentation, j'ai exécuté le generate-core-file commande.Cela a forcé la génération d’un core dump.

Pour vérifier où les core dumps sont générés, exécutez :

sysctl kernel.core_pattern

ou:

cat /proc/sys/kernel/core_pattern

%e est le nom du processus et %t l’heure du système.Vous pouvez le changer /etc/sysctl.conf et rechargement par sysctl -p.

Si les fichiers core ne sont pas générés (testez-le en : sleep 10 & et killall -SIGSEGV sleep), vérifiez les limites en : ulimit -a.

Si la taille de votre fichier principal est limitée, exécutez :

ulimit -c unlimited

pour le rendre illimité.

Ensuite, testez à nouveau, si le core dump réussit, vous verrez « (core dumped) » après l'indication d'erreur de segmentation comme ci-dessous :

Défaut de segmentation :11 (core dumpé)

Voir également: core dumped - mais le fichier core n'est pas dans le répertoire courant ?


Ubuntu

Dans Ubuntu, les core dumps sont gérés par Apport et peut être situé dans /var/crash/.Cependant, il est désactivé par défaut dans les versions stables.

Pour plus de détails, veuillez vérifier : Où puis-je trouver le core dump dans Ubuntu ?.

macOS

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

Peut-être pourriez-vous le faire de cette façon, ce programme est une démonstration de la façon de détecter une erreur de segmentation et de l'envoyer à un débogueur (il s'agit du code original utilisé sous AIX) et imprime la trace de la pile jusqu'au point d'erreur de segmentation.Vous devrez changer le sprintf variable à 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 devrez peut-être ajouter un paramètre supplémentaire pour que gdb vide le noyau, comme indiqué ici dans ce blog. ici.

D'autres éléments peuvent influencer la génération d'un core dump.J'ai rencontré ceux-ci :

  • le répertoire du dump doit être accessible en écriture.Par défaut, il s'agit du répertoire courant du processus, mais cela peut être modifié en définissant /proc/sys/kernel/core_pattern.
  • dans certaines conditions, la valeur du noyau dans /proc/sys/fs/suid_dumpable peut empêcher la génération du noyau.

Il existe d'autres situations pouvant empêcher la génération qui sont décrites dans la page de manuel - essayez man core.

Pour activer le core dump, procédez comme suit :

  1. Dans /etc/profile commentez la ligne :

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

    *               soft    core            0
    
  3. exécuter la cmd limit coredumpsize unlimited et vérifie-le avec 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 le corefile est écrit, vous pouvez tuer le processus associé avec cmd kill -s SEGV <PID> (ne devrait pas être nécessaire, juste au cas où aucun fichier principal ne serait écrit, cela peut être utilisé comme vérification) :

    # kill -s SEGV <PID>
    

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

Pour Ubuntu 14.04

  1. Vérifiez le core dump activé :

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

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

    gedit ~/.bashrc et ajouter ulimit -c unlimited à la fin du fichier et enregistrez, réexécutez le terminal.

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

    Dans le Makefile -O0 -g

  5. Exécutez l'application qui crée un vidage de mémoire (le fichier de vidage de mémoire portant le nom « core » doit être créé à proximité du fichier nom_application) :

    ./application_name
    
  6. Exécuter sous gdb :

    gdb application_name core
    

Par défaut, vous obtiendrez un fichier core.Vérifiez que le répertoire actuel du processus est accessible en écriture, sinon aucun fichier principal ne sera créé.

Mieux vaut activer le core dump par programme à l'aide d'un 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));
}

Attendez.C’est automatiquement le cas.Pas besoin de le faire

Il convient de mentionner que si vous avez un système mis en place, alors les choses sont un peu différentes.Dans la configuration, les fichiers principaux seraient généralement redirigés, au moyen de core_pattern valeur sysctl, via systemd-coredump(8).La limite de taille du fichier principal serait généralement déjà configurée comme "illimitée".

Il est alors possible de récupérer les core dumps en utilisant coredumpctl(1).

Le stockage des core dumps, etc.est configuré par coredump.conf(5).Il existe des exemples sur la manière d'obtenir les fichiers principaux dans la page de manuel coredumpctl, mais en bref, cela ressemblerait à ceci :

Recherchez le fichier 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

Obtenez le fichier principal :

[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top