Hello,
I would like to ask you for a little help with program I'm working on. I have problems with signals and synchronizing processes (I'm quite new to this part of programming).
Process "parent" creates new child process "child1" and this process creates new child process "child2". The "child2" process sends a SIGUSR2 signal to "child1" process to inform that he is ready to do something. When "child1" receives SIGUSR2 from "child2", he sends a SIGUSR2 signal to "parent" process to inform that he is ready too. When "parent" receives SIGUSR2 from "child1", he sends SIGUSR1 to "child1". Now "child1" do something. When finished, "child1" sends SIGUSR2 to "child2". Now "child2" do something. When finished, sends SIGUSR2 to "child1" and ends. When "child1" receives SIGUSR2, he sends SIGUSR2 to "parent" and ends. When "parent" receives SIGUSR2, he does something and ends.
SIGUSR1 SIGUSR1
parent ------------> child1 ------------> child2
<----------- <-----------
SIGUSR2 SIGUSR2
Hope you understand
Below is my code. If you are familiar with signals, can you please cut&paste the code and spend several minutes of your time to try to find what is wrong?
Expected output should be:
- Child2: sending SIGUSR2 to child1
- Child1: child2 is ready
- Parent: child1 is ready
Child1: received signal from parent, do something
Child2: received signal from child1, do something
*** child2 end ***
*** child1 end ***
Parent: received signal from child1, do something
*** parent end ***
But I only get:
- Child2: sending SIGUSR2 to child1
- Child1: child2 is ready
- Parent: child1 is ready
Child1: received signal from parent, do something
And sometimes even without the last sentence.
Thanks you very much for any help.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define true 1
#define false 0
pid_t pid_child2=0, pid_child1=0, pid_parent=0;
sigset_t pMask, pOldMask, cMask, cOldMask;
int child1_ready=0, child2_ready=0;
/* signal handler for parent */
void sig_parent(int sig)
{
if ((sig==SIGUSR2) && (child1_ready==0)) {
child1_ready=1;
printf("* Parent: child1 is ready\n");
kill(pid_child1, SIGUSR1); // send SIGUSR1 to child1
} else
if (sig==SIGUSR2) {
printf("Parent: received signal from child1, do something\n");
printf("*** Parent end ***\n");
exit(0);
}
return;
}
/* signal handler for child1 */
void sig_child1(int sig)
{
if (sig==SIGUSR1) {
printf("Child1: received signal from parent, do something\n");
kill(pid_child2, SIGUSR1); // send SIGUSR1 to child2
} else
if ((sig==SIGUSR2) && (child2_ready==0)) {
child2_ready=1;
printf("* Child1: child2 is ready\n");
kill(pid_parent, SIGUSR2); // inform parent
} else
if (sig==SIGUSR2) {
printf("*** child1 end***\n");
kill(pid_parent, SIGUSR2); // inform parent
exit(0);
}
return;
}
void sig_child2(int sig)
{
if (sig==SIGUSR1) {
printf("Child2: received signal from child1, do something\n");
kill(pid_child1, SIGUSR2); // inform child1
printf("*** child2 end ***\n");
exit(0);
} else
if (sig==SIGUSR2) {
printf("* Child2: sending SIGUSR2 to child1\n");
kill(pid_child1, SIGUSR2); // inform child1
}
return;
}
/* child2 code */
void child2(void)
{
pid_child1=getppid(); // child2 knows its parent (child1)
if (signal(SIGUSR1, sig_child2)==SIG_ERR) {
fprintf(stderr, "Can't catch SIGUSR1.");
}
if (signal(SIGUSR2, sig_child2)==SIG_ERR) {
fprintf(stderr, "Can't catch SIGUSR2.");
}
sig_child2(SIGUSR2); // start the communication
for (;;) sigsuspend(&cOldMask); // wait for signal
}
void child1(void)
{
pid_parent=getppid(); // child1 knows its parent (parent)
sigemptyset(&cMask);
sigaddset(&cMask, SIGUSR1);
sigaddset(&cMask, SIGUSR2);
sigprocmask(SIG_BLOCK, &cMask, &cOldMask);
pid_t pid=fork();
if (pid==0) { // we are in the child process
child2();
} else {
if (pid>0) { // we are in the parent process
pid_child2=pid;
if (signal(SIGUSR1, sig_child1)==SIG_ERR) {
fprintf(stderr, "Can't catch SIGUSR1.");
}
if (signal(SIGUSR2, sig_child1)==SIG_ERR) {
fprintf(stderr, "Can't catch SIGUSR2.");
}
for (;;) { // wait for signals
sigsuspend(&pOldMask);
sigsuspend(&cOldMask);
}
} else {
fprintf(stderr, "Can't create new child.");
}
}
sigprocmask(SIG_UNBLOCK, &cMask, NULL);
return;
}
void parent(void)
{
sigemptyset(&pMask);
sigaddset(&pMask, SIGUSR1);
sigaddset(&pMask, SIGUSR2);
sigprocmask(SIG_BLOCK, &pMask, &pOldMask);
pid_t pid=fork();
if (pid==0) { // we are in child process
child1();
} else {
if (pid>0) { // we are in parent process
pid_child1=pid;
if (signal(SIGUSR2, sig_parent)==SIG_ERR) {
fprintf(stderr, "Can't catch SIGUSR2.");
}
for (;;) sigsuspend(&pOldMask); // wait for signal
} else {
fprintf(stderr, "Can't create new child.");
}
}
sigprocmask(SIG_UNBLOCK, &pMask, NULL);
return;
}
int main()
{
setbuf(stdout,NULL);
parent();
return 0;
}