BUG: newlib 1.17 doesn't flush all line-buffered streams on input

Till Straumann strauman at slac.stanford.edu
Fri Jun 11 05:34:19 UTC 2010

Per standard, when reading from an unbuffered or line-buffered input stream
then all line-buffered output streams must be flushed.

This analysis does not address the REENT_SMALL case

In newlib, streams are 'attached' to a 'reent' struct. The 3 stdio streams
stdin, stderr, stdout are managed 'per-thread' and each thread has
these three streams 'attached' to its struct reent.

Other streams that are created during the lifetime of the system (e.g.,
via fopen) are 'attached' to the GLOBAL_REENT struct.

The __srefill_r() routine, when it finds that it needs to refill a
line- or unbuffered stream, calls (see newlib/libc/stdio/refill.c)

_fwalk(_GLOBAL_REENT, lflush)

which results in all line-buffered output streams 'attached' to
GLOBAL_REENT to be flushed.

However, all the 'stdout' streams which are not attached to GLOBAL_REENT
(but to individual struct reents) are NOT flushed.

As a work-around I'd propose to at least flush the executing thread's
streams by adding a statement

if ( _GLOBAL_REENT != ptr ) {
   _CAST_VOID _fwalk (ptr, lflush);

after _fwalk(_GLOBAL_REENT, lflush);

-- Till

PS: How to reproduce:


printf("Hello"); scanf("%i", &dummy);

PPS: Under rtems-4.10 this bug is obscured by the fact that
the initialization task is actually using _GLOBAL_REENT so that
the above test case (printf/scanf) works as expected from the
initialization task.

More information about the users mailing list