Consider:
int main()
{
if (fork() == 0){
printf("a");
}
else{
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
(from Computer Systems, Bryant - O'Hallaron).
We are asked for all the possible output sequences.
I answered: acbc, abcc, bacc. However, I am missing one output compared to the solution (bcac). I thought this output was not possible because the parent process waits for its child to return before printing c (waitpid). Is this not true? Why? And, in that case, what is the difference between the code above and the same without the waitpid line?
I don't see any way bcac
is possible. At first I expected some trickery based on the stdio buffers being flushed in an unexpected order. But even then:
The child won't output c
until after it has output a
. Therefore the first c
in bcac
must have come from the parent.
The parent won't output c
until after the waitpid
completes. But that can't happen until after the child is finished, including the final stdio flush that happens during exit()
. Therefore the first c
is always from the child.
Proof by contradiction has been achieved... the output can't be bcac
.
Well, there is one thing you could do to mess up the order. You could exec the program inside a process that already has a child which is about to exit. If the pre-existing child exits before the new child prints a
, then the main process will detect that exit with waitpid
, and go ahead and print its stuff and possibly exit before the child prints anything.
This is something to watch out for in setuid programs: don't assume that because your program only created one child process that it only has one child process. If you're in an advanced defensive-code learning context this answer makes sense. In a unix-newbie context it doesn't seem relevant, and it's probably better to just say bcac
is impossible, even though it's technically not true.