Search code examples
clinuxwc

why "Line buffer stdout to ensure lines are written atomically and immediately"


I'm reading the source code of wc command, and in main function I found follow code:

  /* Line buffer stdout to ensure lines are written atomically and immediately
     so that processes running in parallel do not intersperse their output.  */
  setvbuf (stdout, NULL, _IOLBF, 0);

so why line buffer stdout ensure that?


Solution

  • Say block buffering is used for stdout instead of line buffering. (This is the default if stdout refers to a regular file, for example.) Let the buffer size be 1024 bytes (so that output is flushed to the file every 1024 bytes), and pretend that two processes are writing to the same file.

    Say that the first process currently has 1020 bytes in its I/O buffer and writes the line "foo_file 37\n" to stdout. This will put "foo_" at the end of the I/O buffer, flush the buffer to the file (since the buffer is now full), and then put "file 37\n" at the beginning of the buffer. Say that the second process then comes along and flushes its buffer, which happens to start with "bar_file 48\n". The resulting line in the output file will then be "foo_bar_file 48", which clearly isn't what we want.

    The basic problem is that buffer boundaries do not necessarily correspond to line boundaries when block buffering is used.

    You could play around with two instances of the following program writing to the same file to see this effect in action yourself:

    #include <stdio.h>
    
    int main(void) {
        setvbuf (stdout, NULL, _IOLBF, 0);
        for (;;)
            puts("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        return 0;
    }
    

    With the setvbuf() call commented out, you will see some lines get mixed up with other lines. Be aware that this will program will quickly write a huge file, of course. :)