Dean Leitersdorf Dean Leitersdorf - 1 year ago 56
C Question

Extra data printed out after call to fork()

I am running the following code which I wrote in c on my Mac.

#include <unistd.h>
#include <stdio.h>

int main(int argc, const char * argv[]) {

int i = 0;
printf("Starting pid:%d\n", getpid());
int ret = fork();
printf("hello(%d)%d, %d ", i, getpid(), ret);
return 0;}

The goal I had in mind was for there to be 6 prints in total - 3 from the original parent (the pid printed in "Starting pid"), and 1 more from each of the 3 spawned children. Instead what I received was:

Starting pid:7998
hello(1)8009, 0
hello(1)7998, 8009 hello(2)8010, 0
hello(1)7998, 8009 hello(2)7998, 8010 hello(3)7998, 8011 hello(1)7998, 8009 hello(2)7998, 8010 hello(3)8011, 0

Note that the original parent (7998) prints 6 times (three times when i==1, twice with i==2, and once with i==3).

Why would this be happening? Why I am not receiving 3 prints from the parent (once when i==1, i==2, i==3). If we look at it from the parent's perspective - there is a while loop and we are supposed to hit the print statement inside only 3 times.

Is it perhaps that fork is async or something? What am I missing?

Answer Source

When you fork a process, the memory in parent is duplicated in the child. This includes the stdout buffer.

Starting on the second iteration of the loop in the parent, you have hello(1)7998, 8009 in the buffer. When the second child forks, this text is still in that child's buffer. The second child then prints hello(2)8010, 0, then a newline. The newline flushes the child's buffer, so the second child prints this:

hello(1)7998, 8009 hello(2)8010, 0 

After the fork, the parent prints hello(2)7998, 8010 which is added to the output buffer. Then on the third iteration, the third child inherits this and prints:

hello(1)7998, 8009 hello(2)7998, 8010 hello(3)8011, 0

The parent then prints hello(3)7998, 8011 which is again added to the buffer. Then parent then exits the loop and exits, after which the buffer is flushed and the parent outputs:

hello(1)7998, 8009 hello(2)7998, 8010 hello(3)7998, 8011

To correct this, then parent process needs to clear the output buffer before forking.

This can be done either by calling fflush(stdout) after calling printf, or by adding a newline (\n) to the end of the printf.


As a more general solution, calling fflush(NULL) will flush all open output streams.