Next: Manipulation de la pile Up: Problèmes de la gestion Previous: Problèmes de la gestion

Le signal SIGCHLD

Le signal SIGCHLD (anciennement SIGCLD) est un signal utilisé pour réveiller un processus dont un des fils vient de mourir. C'est pourquoi il est traité différemment des autres signaux. La réaction à la réception d'un signal SIGCHLD est de repositionner le bit pendant à zéro, et d'ignorer le signal, mais le processus a quand même été réveillé pour cela. L'effet d'un signal SIGCHLD est donc uniquement de réveiller un processus endormi en priorité interruptible.

Si le processus capture les signaux SIGCHLD, il invoque alors la procédure de traitement définie par l'utilisateur comme il le fait pour les autres signaux, ceci en plus du traitement par défaut.

Le traitement normal est lié à la primitive wait qui permet de récupérer la valeur de retour (exit status) d'un processus fils. En effet, la primitive wait est bloquante et c'est la réception du signal qui va réveiller le processus, et permettre la fin de l'exécution de la primitive wait.

Un des problèmes de la gestion de signaux System V est le fait que le signal SIGCHLD est reçu (raised) au moment de la pose d'une fonction de traitement.

Ces propriétés du signal SIGCHLD peuvent induire un bon nombre d'erreurs.

Par exemple, dans le programme suivant nous positionnons une fonction de traitement dans laquelle nous repositionnons la fonction de traitement. Comme sous System V, le comportement par défaut est repositionné pendant le traitement d'un signal. Or le signal est levé à la pose de la fonction de traitement, d'où une explosion de la pile.

#include <stdio.h>
#include <unistd.h> /* ancienne norme */
#include <signal.h>

void hand(int sig) { 
    signal(sig, hand);
    printf("message qui n'est pas affiche\n");
}

main() {
    signal(SIGCHLD, hand);
    printf("ce printf n'est pas execute\n");
}
Sur les HP, un message d'erreur vous informe que la pile est pleine : stack growth failure.

Deuxième exemple :

#include <signal.h>
#include <sys/wait.h>

int pid, status;

void hand(int sig) {
    printf(" Entree dans le handler \n");
    system("ps -l");                 /* affichage avec etat zombi du fils */
    if ((pid = wait(&status)) == -1) /* suppression du fils zombi */
    {
         perror("wait handler ");
         return ;
    }
    printf(" wait handler  pid: %d    status %d \n", pid, status);
    return;
}

main() {
    signal(SIGCHLD,hand);  /* installation du handler */
    if (fork() ==  0)
    {   /* dans le fils */
        sleep(5);
        exit(2);
    } 
/* dans le pere */
    if ((pid = wait(&status)) == -1) /* attente de terminaison du fils */
    {
        perror("wait main ");
        return ;
    }
    printf(" wait main  pid: %d    status %d \n", pid, status);
}
résultat:
 Entree dans le handler 
F S  UID   PID  PPID  C PRI NI     ADDR   SZ  WCHAN    TTY  TIME COMD
1 S  121  6792  6667  0 158 20  81ac180    6  49f5fc  ttys1 0:00 sigchld
1 S  121  6667  6666  0 168 20  81ac700  128 7ffe6000 ttys1 0:00 tcsh
1 Z  121  6793  6792  0 178 20  81bda80    0          ttys1 0:00 sigchld
1 S  121  6794  6792  0 158 20  81ac140   78  4a4774  ttys1 0:00 sh
1 R  121  6795  6794  4 179 20  81bd000   43          ttys1 0:00 ps
wait handler  pid: 6793    status 512     (2 * 256)
wait main: Interrupted system call
A la mort du fils, Le père reçoit le signal SIGCHLD (alors qu'il était dans le wait du main), puis le handler est executé, et ps affiche bien le fils zombi. Ensuite c'est le wait du handler qui prend en compte la terminaison du fils. Au retour du handler, l'appel a wait du main retourne -1, puisqu'il avait été interrompu par SIGCHLD.

Next: Manipulation de la pile Up: Problèmes de la gestion Previous: Problèmes de la gestion

Dominique REVUZ
Mon Feb 2 12:10:31 MET 1998
Une Bug Un mail Merci