J'ai besoin d'envoyer un signal à un processus enfant 3 fois.

Le problème est que l'enfant ne reçoit le signal qu'une seule fois, puis se transforme en zombie.

Le résultat attendu serait:

Je suis l'enfant 11385 et j'ai reçu SIGUSR1

Je suis l'enfant 11385 et j'ai reçu SIGUSR1

Je suis l'enfant 11385 et j'ai reçu SIGUSR1

Mais le vrai résultat est:

Je suis l'enfant 11385 et j'ai reçu SIGUSR1

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

void my_handler()
{
  printf("\n I'm the child %i and i received SIGUSR1\n", getpid());
}


int main (int argc, char **argv) {
    int *array;
    int N = 10;
    int i;
    pid_t pid1;
    array=(int*)malloc(sizeof(int)*N);


    signal(SIGUSR1,my_handler);

    for (i = 0; i< N; i++) 
    {
        pid1 = fork();
        if(pid1 < 0)
        {
            exit(EXIT_FAILURE);
        }
        else if (pid1 > 0)
        {
            array[i]= pid1;
        }

        else
        {   
            sleep(100);
            exit(EXIT_SUCCESS);
        }
    }

    i=0;
    while(i<3) // I need to call the son 3 times
    {
        kill(array[1], SIGUSR1);
        i++;
    }
}
0
José Antonio Camus Godoy 5 avril 2017 à 21:38

2 réponses

Meilleure réponse

Lorsque l'enfant reçoit le signal, il attend probablement la fin du sleep. Le premier signal interrompra le sleep même si le temps n'a pas expiré, le faisant revenir avec errno réglé sur EINTR. Si vous voulez qu'il continue à dormir, vous devez appeler sleep à nouveau.

1
rici 5 avril 2017 à 19:05
  • votre processus parental s'est terminé sans attendre l'enfant
  • Les signaux pourraient être envoyés trop vite, j'ai ajouté un court délai
  • j'ai ajouté plus de retards
  • la signature correcte pour un gestionnaire de signaux est void handler(int signum) Ceci est crucial, car le gestionnaire est appelé avec un argument, et la disposition de la pile est différente pour les gestionnaires de signaux.
  • vous ne devez pas appeler printf () depuis un gestionnaire de signaux, ce n'est pas asynchrone.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

char pidstr[10];
char massage[]="        I'm the child and i received SIGUSR1\n";

#define CNT 1
void my_handler(int signum)
{
write(0, massage, strlen(massage));
}


int main (int argc, char **argv) {
    int i , err, status;
    pid_t pid1;
    int array[CNT];

    signal(SIGUSR1, my_handler);

    for (i = 0; i< CNT; i++) {
        pid1 = fork();
        if(pid1 < 0) { exit(EXIT_FAILURE); }
        else if (pid1 > 0) {
                printf("ChildPid=%d\n", pid1 );
            array[i]= pid1;
        }

        else
        {   // child
                // signal(SIGUSR1, my_handler);
            sprintf(pidstr,"[%d]", getpid() );
            memcpy (massage,pidstr, strlen(pidstr));
            sleep(10);
                printf("Unslept\n");
            sleep(10);
                printf("Unslept\n");
            sleep(10);
                printf("Unslept\n");
            exit(EXIT_SUCCESS);
        }
    }
    sleep(10);
    for (i=0; i<3; i++) {
        err = kill(array[0], SIGUSR1);
        printf("Err=%d:%d\n", err, (err) ? errno: 0 );
        sleep(1);
    }

    while ( (pid1=wait( &status)) != -1){
        printf("[Parent] Reaped %d\n", pid1);
        }

return 0;
}
1
wildplasser 5 avril 2017 à 20:00