Reputation: 3
I have the following program which I have almost solved:
There are two processes: a parent process (P0) creates five children; after that, the parent process sends five times a SIGUSR1 signal to each of its children and goes sleeping for 1 second. Then, the parent process sends a SIGQUIT signal to each child and waits for all of them to terminate.
Each child process:
- waits for a signal: if a SIGQUIT signal arrives, the child process exits; if a SIGUSR signal arrives, then the child prints the text "Even, PID = ..." if it has an even PID, "Odd, PID = ..." otherwise. The child process must not terminate before it has received the SIGQUIT signal from the parent.
Make sure that the execution of the SIGUSR1 signal handler can't be stopped by the incoming of a SIGQUIT signal.
Now, this is what I've got so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define NUM_CHILDREN 5
#define NUM_ITER 5
void sigusr1_handler(int sig);
int main(void) {
int i;
pid_t children[NUM_CHILDREN];
struct sigaction act;
struct sigaction act2;
act.sa_handler = sigusr1_handler;
act.sa_flags = 0;
sigaddset(&act.sa_mask,SIGQUIT);
sigaction(SIGUSR1,&act,0);
sigaction(SIGQUIT,&act,0);
for(i = 0; i < NUM_CHILDREN; i++) {
figli[i] = fork();
switch(figli[i]) {
case -1:
fprintf(stderr,"Error with fork()!");
exit(EXIT_FAILURE);
case 0:
while(1) pause();
exit(EXIT_SUCCESS);
default:
break;
}
}
for(i = 0; i < NUM_ITER; i++) {
for(i = 0; i < NUM_CHILDREN; i++) {
kill(children[i],SIGUSR1);
sleep(1);
}
}
for(i = 0; i < NUM_CHILDREN; i++) {
kill(children[i],SIGQUIT);
}
for(i = 0; i < NUM_CHILDREN; i++) {
wait(NULL);
}
exit(EXIT_SUCCESS);
}
void sigusr1_handler(int sig) {
if(sig == SIGUSR1) {
if((getpid() % 2)==0)
printf("Even, PID = %d\n",getpid());
else printf("Odd, PID = %d\n",getpid());
}
if(sig == SIGQUIT) exit(0);
}
I've already looked up how to block signals when handling other ones and I can't use sigprocmask() (as this is a course exercise and we didn't use that function). I don't understand if my solution is working properly, if I try to send a SIGQUIT signal when each child is handling the SIGUSR1 signal (for example by sending it from terminal with CTRL-\ ) I get two scenarios:
if(sig == SIGQUIT) exit(0)
line in the sigusr1_handler
function, the program doesn't stop and I get this output:Even, PID = 5296
^\Odd, PID = 5297
Even, PID = 5298
Odd, PID = 5299
Even, PID = 5300
but then the program gets stuck because none of the children is handling the SIGQUIT signal the parent is sending; if I put the if(sig == SIGQUIT) exit(0)
line in the handler, then pressing CTRL - \ makes the program stop, making both parent and children exit. I'm not sure but I thought this could happen because when I send the SIGQUIT signal with CTRL - \ and the program is running, I'm not actually sending the signal to the children but to the parent process (?), therefore with another terminal I've tried to send a SIGQUIT signal with kill(pid,signal)
to one of the children running in that moment, but this doesn't seem to work properly.
Any suggestions?
Upvotes: 0
Views: 100