This is the mail archive of the
libstdc++@sourceware.cygnus.com
mailing list for the libstdc++ project.
problem with flush on file streams
- To: libstdc++ at sourceware dot cygnus dot com
- Subject: problem with flush on file streams
- From: scott snyder <snyder at fnal dot gov>
- Date: Mon, 08 Nov 1999 14:22:41 -0600
hi -
Continuing to test the new libstdc++, i've run into a problem with the
flush() method on file streams. This is based on the current version
in cvs, using gcc 2.95.2 on a i686-pc-linux-gnu platform.
Consider the following program:
----------------------------------------------------
#include <iostream>
main ()
{
cout << "a\n";
cout.flush ();
cerr << "b\n";
cerr.flush ();
cout << "c\n";
cout.flush ();
}
----------------------------------------------------
Now, i understand that in the absence of any explicit flushes,
the ordering of output to different streams which go to the same
file is not guaranteed. But, with the inclusion of the explicit
flushes above, i would expect this program to always produce output
in the order in which the calls are made in the program.
However, this is not the case. When i run the program with no redirection,
i get the expected result:
$ ./test4
a
b
c
On the other hand, if i redirect stdout and stderr to a file, i get:
$ ./test4 >& x
$ cat x
a
c
b
which is not expected.
If i look in the debugger at what happens as a result of the cerr.flush()
call, i see in basic_filebuf::sync:
virtual int
sync()
{
// Don't do anything about input sequences.
bool __testput = _M_out_cur && _M_out_beg < _M_out_cur;
if (__testput)
{
// Iff _M_mode is ios_base::out only, then need to set out
// pointers to the end of the current put sequence before
// we call _M_really_overflow, or else the stream will not be
// flushed. Back up, so overflow doesn't append extra characters.
this->_M_really_overflow();
}
_M_last_overflowed = false;
return 0;
}
that __testput is false, thus _M_really_overflow() does not get called.
I'm guessing that what happens is that after the `cerr << "b\n";', the
C++ streambuf is flushed to the libio layer, and it gets buffered there.
When flush() is called, we see that the C++ buffer is empty and thus
don't do anything, even though there is still data buffered at the
layer below.
I tried to see what would happen if i called the libio sync()
unconditionally here:
1999-11-08 scott snyder <snyder@fnal.gov>
* bits/std_fstream.h (basic_filebuf::sync): Unconditionally call
_M_file->sync().
--- std_fstream.h-orig Sun Nov 7 20:42:39 1999
+++ std_fstream.h Sun Nov 7 20:43:01 1999
@@ -170,6 +170,7 @@
// flushed. Back up, so overflow doesn't append extra characters.
this->_M_really_overflow();
}
+ _M_file->sync ();
_M_last_overflowed = false;
return 0;
}
With this change, i get the expected output in both the redirected
and non-redirected cases. But i don't really understand the
libstdc++/libio interaction enough to be sure that this is a correct
fix.
thanks,
sss