|
Boost : |
Subject: [boost] [iostreams] filtering_ostream does not flush std::cout.
From: Duncan Smith (duncanphilipnorman_at_[hidden])
Date: 2010-09-01 10:33:11
I'm using Boost 1.43.0, and I've found that filtering_ostream does not
flush "std::cout". I found a relevant (and recent) ticket against
Boost 1.44.0, but my issue is slightly different.
https://svn.boost.org/trac/boost/ticket/4590
I'm using GCC 4.3.4 on Gentoo Linux.
I'm hoping that I'm just doing something wrong, but if you think
there's a bug, I'll add my testcase to the ticket.
The basic recipe:
filtering_ostream out;
out.push(any_filter_at_all());
out.push(std::cout);
out << "Hello World!" << std::flush;
sleep(10); // Observe an empty console.
std::cout << std::flush;
sleep(10); // Observe printed text on console.
This problem is quite bad for me when doing the following on the
command-line (for a more complicated program):
./program 2>&1 | tee some-file.log
Because stdout is not getting flushed, the stdout and stderr get
intermingled strangely.
However, disabling buffering on stdout works around the problem:
stdbuf --output=0 ./program 2>&1 | tee some-file.log
Please tell me if you think there's a bug in my code. If it's a bug
in Boost.Iostreams (or I'm expecting the wrong behaviour), I would
appreciate any ideas for workarounds (I tried cout.setf(unitbuf), and
that doesn't seem to do the trick).
Here's the full text of my code:
------------------
// Test case for flushing a filtering_ostream based on the
// boost_iostreams_filtering_ostream.cpp attached to ticket #4950:
// https://svn.boost.org/trac/boost/ticket/4590
// https://svn.boost.org/trac/boost/attachment/ticket/4590/boost_iostreams_filtering_ostream.cpp
// changed to use "cout" as the sink.
//
// Flushing a filtering_ostream using the flush() global function does not work
// in Boost 1.43. I suspect it also does not work in Boost 1.44.
//
// Using GCC-4.3.4 on Gentoo Linux.
//
#include <cassert>
#include <string>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
// Included for "sleep()" call below.
#include <unistd.h>
namespace io = boost::iostreams;
// Simple output filter forwarding just forwarding the put chars to
// the sink.
struct transparent_output_filter {
typedef char char_type;
typedef io::output_filter_tag category;
template <typename Sink>
bool put(Sink& snk, char c)
{
return io::put(snk, c);
}
};
int main(int argc, char *argv[])
{
using namespace std;
io::filtering_stream<io::output> out;
// Transparent filter just forward the characters to the sink.
//
// Note: I observe this behaviour with and without this line.
out.push(transparent_output_filter());
// Sink appends characters to "cout".
out.push(cout);
// Write test string to filtering_ostream.
out << "Hello World!";
// On my system, this will flush the buffer iff I'm on an
// interactive console. "\n" and endl have the same effect. I believe
// that my shell sets "stdout" to be line-buffered if it's interactive.
// out << "\n";
bool wasFlushed = false;
// The flush does *not* work in Boost 1.43.
wasFlushed = io::flush(out);
// This assertion does not go off, though.
assert(wasFlushed);
// This also doesn't work.
wasFlushed = out.flush();
assert(wasFlushed);
// This also doesn't work.
out << std::flush;
// Demonstrate that none of the above flush calls had any effect on "cout".
sleep(10);
// Now we finally get the characters on the console.
cout << flush;
// Demonstrate that the direct flush call works when called directly on
// "cout".
sleep(10);
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk