Boost logo

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.
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 << "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:
// 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.

    // Sink appends characters to "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.

    // This also doesn't work.
    wasFlushed = out.flush();

    // This also doesn't work.
    out << std::flush;

    // Demonstrate that none of the above flush calls had any effect on "cout".

    // Now we finally get the characters on the console.
    cout << flush;

    // Demonstrate that the direct flush call works when called directly on
    // "cout".

    return 0;

Boost list run by bdawes at, gregod at, cpdaniel at, john at