So I wrote a test program and here is the code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
printf("%s", "entering\n");
fflush(stdout);
for (i = 0 ; i < 3 ; i++)
{
fork();
fflush(stdout);
}
printf("%s", "exiting\n");
}
When I compile and run it in the terminal it displays what I expect it to: “entering” once, and “exiting” some times. When I run it and redirect the output to a file it displays entering for every exiting.
1) Why does it not output the same thing to terminal and to a file every time?
2) Why does it display entering in the file 8 times but not entering in in the terminal only once (once is what I would expect it to do).
3) Do the fflush() statements make a difference when my output goes to a file?
It has to do with the buffering on the standard file handles. From ISO C99
7.19.3/7 Files:When you’re writing to the terminal, the output is most likely (a) line-buffered, meaning it will be flushed whenever a newline is sent.
With redirection, it’s fully buffered meaning it will only flush when the buffer is full.
You can use
setvbufbefore operating onstdout, to set it to unbuffered or line buffered, and you won’t have to worry about flushing.Just keep in mind that unbuffered output may affect performance quite a bit if you’re sending the output to a file. Also keep in mind that support for this is implementation-defined, not guaranteed by the standard.
C99 section 7.19.3/3 is the relevant bit:
(a) Whether standard input and output are unbuffered or line buffered where the underlying file is possibly interactive is not specified by the standard (see here). Line buffering is the most common (by far) from what I’ve encountered.
As to why you’re getting multiple
enteringmessages even though you flush it before forking, that’s a trickier one. You haven’t listed your environment so this is supposition at best but I see a few possibilities (although there may well be more).Firstly, the
fflushmay be failing for some reason. This is actually possible but easy to check since it behaves similarly towrite(because it usually callswriteunder the covers).In other words, check
errnoafter the flush to see if there’s been a problem. If so, the C runtime buffers will still be unflushed in all children so they’ll all writeentering.Secondly, even if the buffers are flushed, there may be more buffering going on below (at the
writelevel or within the terminal drivers themselves) which is duplicated by thefork, resulting in multiple outputs to the terminal. I consider this unlikely.Thirdly, this may just be a weird platform-specific issue. When I run your code on my Ubuntu 11.04 box, I see no difference between the terminal output and the file output variants. They both output one
enteringand eightexitingmessages.If that third one is the case then you really have no recourse: ISO C doesn’t mandate what happens in this case because ISO C knows nothing of
fork. I can’t find anything in POSIX.1 that seems to indicate one way or another but it may be there.For what it’s worth, if I comment out only the first
fflush, I getenteringtwice followed by eightexitingmessages. If I comment out only the second, it asts the same as if they’re both there, oneenteringfollowed by eightexiting.If I comment out both of them, I get eight
entering/exitingpairs.