Having child processes printf to redirected stdout correctly

587 Views Asked by At

I am redirecting stdout on a process with freopen(), and as long as it's just one process, everything's fine.

However, if I do something like this:

freopen("stdout.txt", "a+", stdout);
printf("Initial line.\n");

int i=0;
while(i<1000)
    {
        if(fork())
            wait(NULL);
        else
            printf("Line %d.\n", i);
        i++;
    }

The first printed lines are re-printed on the file over and over. Is there anything particular I should do to avoid this from happening?

1

There are 1 best solutions below

4
On BEST ANSWER

The first printed lines are re-printed on the file over and over.

This is because the standard C library applies buffering to the standard output stream when using stdio functions. In particular, when stdout is redirected to a file, the buffering mode changes from line-buffered to fully buffered (with a buffer of size defined by the library). In line-buffered mode, the buffer gets flushed (and the data actually written) only when a newline is encountered, but in fully buffered mode this only happens when the maximum buffer size is reached.

When you create multiple processes, they all share the same buffer of the parent. Since you do not reach the end of the buffer before spawning new children, and you do not empty it, they will all have the same buffer content. After that, when each of the children dies, the buffer will be automatically flushed by the standard library.

Is there anything particular I should do to avoid this from happening?

Yes. Flush the buffer before creating children.

freopen("stdout.txt", "a+", stdout);
printf("Initial line.\n");
fflush(stdout);

// ...

You also probably want to exit() before the next cycle after the child has done its job:

int i=0;
while(i<1000)
{
    if(fork()) {
        wait(NULL);
    } else {
        printf("Line %d.\n", i);
        exit(0);
    }

    i++;
}