thread safety level of fwide

Alexandre Oliva
Wed Nov 19 20:33:00 GMT 2014

On Nov 19, 2014, MaShimiao <> wrote:

> After reading it's source code, I think it should be marked with race:stream.
> The reasoning is fwide() uses fp several times inside without holding the lock over all of them.

> How do you think about that?

The uses of fp, although technically racy, are well-defined, because of
the way stream orientation works: once it's decided, it never changes,
so it is safe to test, before taking a lock, whether it is already
decided and use the settled value if so.  It is only if it is not
decided yet (when _mode is zero) and we want to set a value (when mode
is nonzero) that we have to resort to mutual exclusion to serialize mode

Torvald, this is another of those “technically a race, but arguably
safe” cases that you've been looking for in glibc.  This idiom of using
“undecided” initial values tested before taking locks is quite common in
IOstreams, in TLS infrastructure, and in various __have_*
feature-testing caches throughout glibc.

> The fwide()'s code is as follows:
> int
> fwide (fp, mode)
>      _IO_FILE *fp;
>      int mode;
> {
>   int result;

>   /* Normalize the value.  */
>   mode = mode < 0 ? -1 : (mode == 0 ? 0 : 1); 

>   if (mode == 0 || fp->_mode != 0)
>     /* The caller simply wants to know about the current orientation
>        or the orientation already has been determined.  */
>     return fp->_mode;

>   _IO_acquire_lock (fp);
>   result = _IO_fwide (fp, mode);
>   _IO_release_lock (fp);

>   return result;
> }

Alexandre Oliva, freedom fighter
You must be the change you wish to see in the world. -- Gandhi
Be Free! --   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

More information about the Libc-help mailing list