Reputation: 1811
I was trying to understand forks, and tried following in C:
#include<stdio.h>
#include <unistd.h>
void forker()
{
printf("%d: A\n",(int)getpid());
fork();
wait();
printf("%d: B\n",(int)getpid());
printf("%d: C\n",(int)getpid());
fork();
wait();
printf("%d: D\n",(int)getpid());
}
int main(void)
{
forker();
return 0;
}
When I compiled and ran resultant a.out, here is what I observed:
> ./a.out
3560: A
3561: B
3561: C
3562: D
3561: D
3560: B
3560: C
3563: D
3560: D
However when I do the following:
> ./a.out > t.txt
something weird happens:
> cat t.txt
3564: A
3565: B
3565: C
3566: D
3564: A
3565: B
3565: C
3565: D
3564: A
3564: B
3564: C
3567: D
3564: A
3564: B
3564: C
3564: D
Can someone please explain this behavior? Why is the output different when it is redirected to a file?
I am using Ubuntu 10.10, gcc version 4.4.5.
Upvotes: 6
Views: 645
Reputation: 62439
The problem is that the output of printf
is passed through a library buffer before being sent to the file, which causes the strange behavior you mentioned. If you add a fflush(stdout)
after each printf
your output will be correct also inside the file.
You can read more about this here: http://www.pixelbeat.org/programming/stdio_buffering/
Upvotes: 3
Reputation: 6137
The other answers do not exactly describe what is happening, and I had to think a bit more to understand. So, in the second case (output buffered because of file redirection), and by using 1,2,3 and 4 instead of 3564, 3565, 3566 and 3567:
At this point, the contents of the 4 internal stdout buffers are:
- process 1:
A:1
B:1
C:1
D:1
- process 2:
A:1
B:2
C:2
D:2
- process 3:
A:1
B:2
C:2
D:3
- process 4:
A:1
B:1
C:1
D:4
This behavior is not happening when stdout is the shell, or with fflush()
, because the stdout buffer is dumped before each fork()
, so only empty buffers are duplicated.
Upvotes: 2
Reputation: 39797
The reason this happens is data buffering. At the time of the fork(), in the case of directing to a file, your output has not been flushed yet... so both the parent and the child now have outstanding output buffers.
Put a call to fflush(stdout);
before each fork();
to resolve this.
Upvotes: 10