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);
}