1

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.

4
  • You're not sending the signal until after both children have exited. How do you expect the child to process the signal? Commented Nov 8, 2022 at 17:00
  • 2
    Obligatory aside: printf is not an async-signal-safe function, as outlined in man 7 signal-safety. Commented Nov 8, 2022 at 17:01
  • 1
    @Oka Neither is exit() Commented Nov 8, 2022 at 17:02
  • Did you really intend to read the same variable from the pipe that you're using to control the number of iterations? Commented Nov 8, 2022 at 17:04

1 Answer 1

0

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); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.