Dervin Thunk
Dervin Thunk

Reputation: 20139

Are both calls to `fprintf(stdout, ...)` and `fprintf(stderr, ...)` guaranteed to non-interleave with multiple threads?

Say I have two threads that print something (relatively long) either to stderr or stdout, is the function to both these streams thread-safe in the sense that they will never "interleave" characters? So, for example, if I have "Hello, World", I will never get "HHellllo,, WorldWorld" Or whatever other interleaving? This is for x86, GCC, Linux > 3.0.

Upvotes: 4

Views: 2624

Answers (2)

Joseph Quinsey
Joseph Quinsey

Reputation: 9972

No. Even in a single-threaded program you can get interleaving because of different buffering rules. By default, stdout is line-buffered while stderr is unbuffered. You can make them both unbuffered via:

   setvbuf(stdout, NULL, _IONBF, 0)

See also stdout thread-safe in C on Linux?, particularly R.'s answer. And also Jonathan Leffler's comment.

Edit: By default, stdout will be fflush'd at the end of each line or when the buffer is full. The latter could occur in the middle of a line. Then, if stdout and stderr both have the same underlying file descriptor, the output fprintf(stderr,... could be inserted into the middle of a line.

But it can be worse. Often you wish to redirect both stderr and stdout to a file or pipe. The man page for setbuf(3) on my system notes:

If a stream refers to a terminal (as stdout normally does) it is line buffered. The standard error stream stderr is always unbuffered by default.

So in this case, stdout becomes block-buffered, and in practice it seems that almost every output to stderr is interleaved with that of stdout. This can be alleviated by addding:

   setlinebuf(stdout);

Or by making stdout unbuffered.

Upvotes: 3

Drew MacInnis
Drew MacInnis

Reputation: 8587

I took a look at glibc, and each call to vfprintf will call the POSIX flockfile (_IO_flockfile) and funlockfile (_IO_funlockfile) on the stream.

So, the characters within a call won't get interleaved with characters from a call from another thread as only one thread can hold the lock on stdout or stderr.

All bets are off as to the ordering of multiple calls across the various threads though.

Upvotes: 6

Related Questions