Reputation: 20139
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
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
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