Reputation: 59
I wrote a program that calls fork()
two times, generating three children and a parent.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int child1 = fork();
int child2 = fork();
// Check for error
if (child1 < 0 || child2 < 0) {
fprintf(stderr, "A fork failed :(\n");
exit(1);
}
// Parent Process
if (child1 > 0 && child2 > 0) {
waitpid(child1, NULL, 0);
waitpid(child2, NULL, 0);
printf("I'm the parent\n");
}
// Child B -- CONFUSION AREA --
else if (child1 > 0 && child2 == 0) {
waitpid(child1, NULL, 0); // Not waiting for process to finish
printf("I'm child B\n");
}
// Child A
else if (child1 == 0 && child2 > 0) {
waitpid(child2, NULL, 0);
printf("I'm child A\n");
}
// Child C
else if (child1 == 0 && child2 == 0) {
printf("I'm child C\n");
}
return 0;
}
I'm trying to print out
I'm child C
I'm child A
I'm child B
I'm the parent
but instead, the program prints out
I'm child B
I'm child C
I'm child A
I'm the parent
I'm confused why child B isn't waiting for child1
process to finish?
I drew a process tree to try and understand what is going on, and my understanding is that it looks like:
/*
Parent (15543)
child1 = 15544;
child2 = 15545
/ \
/ \
/ \
A (15544) B (15545)
child1 = 0; child1 = 15544;
child2 = 15546; child2 = 0;
/
/
/
C (15546)
child1 = 0;
child2 = 0;
*/
Upvotes: 0
Views: 143
Reputation: 12668
When you execute the first fork()
, both processes (parent and child) go to the second fork()
and generate the two other processes you see in the tree. This is the reason you see a grandchild in the output. You think there are only two forks executed, so two children are expected, but you have not realized that the second fork()
is actually executed by two processes: the parent and the child of the first fork()
call.
BTW, the kernel schedules the processes in any order, so you can expect different order in the output lines. Child B cannot waitpid()
as it has not started any child (it is the child B in your tree, It has the pid that the parent got for child A, but child A is not its child, so waitpid()
gives you an error, that you don't examine, and so the printing is done) You assumed it was a parent because one of the child variables was > 0, but he inherited that variable initialized from its parent, as it didn't execute a fork()
call.
Upvotes: 1
Reputation: 1574
When child B calls waitpid()
the call fails and returns -1 because the parent is already waiting on child A, and you can't reap a child process twice.
For the behavior you want, you may be better off using inter-process semaphores to synchronize your process execution. Try including semaphore.h
and take a look at the documentation for sem_init()
.
Upvotes: 1