Reputation: 37
I'm studying IPC using pipes. The parent process creates 'n' number of child processes and waits until all children processes terminate. I want the first child to be notified when all it's sibling processes terminate. I'm exploiting the fact that the read()
blocks till all it's WRITE ends are closed. So, it's siblings close()
the WRITE end upon completing their work.
The problem in my code is, the read()
in the first child does not unblock at all and the first child does not terminate and hence the parent continues to wait.
What is it that I'm doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int fd[2]; // 0 = READ end, 1 = WRITE end
int ret = pipe(fd);
pid_t wait_pid;
int status = 0;
int n = 4;
for(volatile int i = 0;i < n;++i) {
ret = fork();
if(ret == -1) {
fprintf(stderr, "fork failed\n");
exit(1);
}
switch(ret) {
// child
case 0: {
fprintf(stderr, "Child created : %d\n", getpid());
if(i!=0) {
close(fd[0]); // close unused READ end
foo(); // do some work
close(fd[1]); // close WRITE end, the last child
// to close will cause the read()
// of first child to unblock
}
if(i==0) { // first child
close(fd[1]); // close unused WRITE end
foo(); // do some work
char c = 0;
fprintf(stderr, "1st Child's wait started %d\n",
getpid());
read(fd[0], &c, 1); // blocking call, until all
// siblings close the WRITE
// end
fprintf(stderr, "1st Child's wait over %d\n",
getpid());
close(fd[0]); // close READ end
}
fprintf(stderr, "Child %d terminating\n", getpid());
exit(0);
break;
}
}
}
// Parent waits for all childdren to finish
while ((wait_pid = wait(&status)) > 0);
fprintf(stderr, "Parent's wait over, now terminating...\n");
return 0;
}
Upvotes: 3
Views: 1094
Reputation: 70472
The problem with your technique is that the parent itself also has a copy of the file descriptors created by the pipe
.
Close the descriptors after the fork
loop is done.
Upvotes: 3