Home > OS >  Sending signal from parent to child process after parent waits in C program
Sending signal from parent to child process after parent waits in C program

Time:11-09

I am attempting to send SIGUSR1 to my child process, child_b, after my parent process waits. However, my handler for sigusr1 is not executing and printing my message "pong quitting" at the end of the output.

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


int fd[2][2];

void sig_handler(int signum) {
    if (signum == SIGUSR1) {
        printf("pong quitting\n");
        exit(1);
    }
}

void f1() {
    int x = 0;
    close(fd[0][0]);
    close(fd[1][1]);
    while (x <= 100) {
        printf("ping: %d\n", x);
        x  ;
        if (write(fd[0][1], &x, sizeof(int)) < 0) {
            printf("Error writing f1\n");
        }
        if (read(fd[1][0], &x, sizeof(int)) < 0) {
            printf("Error reading f1\n");
        }
    }
    close(fd[0][1]);
    close(fd[1][0]);

} 

void f2() {
    int x = 0;
    close(fd[0][1]);
    close(fd[1][0]);
    while (x <= 100) {
        if (read(fd[0][0], &x, sizeof(int)) < 0) {
            printf("Error reading f2\n");
        }
        if (x <= 100)
            printf("pong: %d\n", x);
        x  ;
        if (write(fd[1][1], &x, sizeof(int)) < 0) {
            printf("Error writing f2\n");
        }
    }
    close(fd[0][0]);
    close(fd[1][1]);
}

int main(void) {

    for (int i = 0; i < 2; i  ) {
        if (pipe(fd[i]) < 0) {
            printf("Error opening pipe.\n");
            return 1;
        }
    }

    pid_t child_a = fork();

    if (child_a < 0) {
        printf("Error forking child_a.\n");
        return 2;
    }

    if (child_a == 0) {
        f1();
    } else {
        pid_t child_b = fork();

        if (child_b < 0) {
            printf("Error forking child_b.\n");
            return 3;
        }

        if (child_b == 0) {
            signal(SIGUSR1, sig_handler);
            f2();
        }

        else {
            waitpid(child_a, NULL, 0);
            waitpid(child_b, NULL, 0);
            kill(child_b, SIGUSR1);
        }
    }

    return 0;
}

I've tried sleeping both the parent and child, as well as rearranging the order of wait and kill; however, I can not get the signal handler to execute. Any help would be appreciated.

CodePudding user response:

Killing after wait is just fundamentally wrong: the program is dead and gone, you'd either be getting ESCHR or kill an innocent unrelated process.

If you move the wait before kill, then the problems become child_b finishing two quickly (try running it under strace -f and see child_b is already a zombie by the time the kill runs). Adding some sleep(a_lot); or pause(); at the end of child_b would help there.

    if (child_b == 0) {
        signal(SIGUSR1, sig_handler);
        f2();
        pause(); // 
    }

    else {
        waitpid(child_a, NULL, 0);
        kill(child_b, SIGUSR1); //^
        waitpid(child_b, NULL, 0); //v
    }

For added async-signal safety, you could also change the handler to be async-signal-safe:

void sig_handler(int signum) {
    char m[]="pong quitting\n";
    write(1,m,sizeof(m)-1);
    _exit(1);
}
  • Related