Boost C++ Libraries: Ticket #4590: Flushing a filtering_ostream stopped working in Boost 1.44 https://svn.boost.org/trac10/ticket/4590 <p> Since the update to Boost 1.44, flushing an filtering_ostream containing an output_filter and a sink different from std::cout (tested boost::iostreams::back_inserter(std::string) and boost::test_tools::output_test_stream) using the flush() member function stopped working. The output string stays empty. This used to work until Boost 1.43. </p> <p> I tried to replace the call of flush() with the sync() member function documented in &lt;<a href="http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/classes/filtering_stream.html">http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/classes/filtering_stream.html</a>&gt;, which leads to compiler error that filtering_ostream does not have this member function. Only using the member function strict_sync() flushes correctly the filtering_ostream in Boost 1.44. </p> <p> Attached is a test case based on the back_inserter example in &lt;<a href="http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/tutorial/container_sink.html">http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/tutorial/container_sink.html</a>&gt; augmented by a transparent filter simplified from the code example in &lt;<a href="http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/concepts/output_filter.html">http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/concepts/output_filter.html</a>&gt;. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4590 Trac 1.4.3 t0rt1e@… Wed, 25 Aug 2010 10:29:49 GMT attachment set https://svn.boost.org/trac10/ticket/4590 https://svn.boost.org/trac10/ticket/4590 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_iostreams_filtering_ostream.cpp</span> </li> </ul> <p> Test case </p> Ticket tort1e@… Wed, 25 Aug 2010 13:08:30 GMT <link>https://svn.boost.org/trac10/ticket/4590#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4590#comment:1</guid> <description> <p> Maybe I should mention the platform, on which I observed this behavior: Mac OS X 10.6 x86_64 with Boost 1.44 installed through <a class="missing wiki">MacPorts</a>. </p> </description> <category>Ticket</category> </item> <item> <author>duncanphilipnorman@…</author> <pubDate>Wed, 08 Sep 2010 19:44:10 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4590 https://svn.boost.org/trac10/ticket/4590 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp</span> </li> </ul> <p> Testcase for linux that shows that even <code>cout</code> does not actually get flushed. </p> Ticket duncanphilipnorman@… Wed, 08 Sep 2010 19:53:03 GMT cc set https://svn.boost.org/trac10/ticket/4590#comment:2 https://svn.boost.org/trac10/ticket/4590#comment:2 <ul> <li><strong>cc</strong> <span class="trac-author">duncanphilipnorman@…</span> added </li> </ul> <p> I've attached <a class="attachment" href="https://svn.boost.org/trac10/attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Attachment 'boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp' in Ticket #4590">boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp</a><a class="trac-rawlink" href="https://svn.boost.org/trac10/raw-attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Download">​</a>, which demonstrates (on Linux) that even <code>std::cout</code> does not get flushed by <code>filtering_ostream</code>. </p> <p> I'm using: </p> <ul><li>GCC 4.3.4 </li><li>Gentoo Linux </li><li>Boost 1.43.0 </li></ul><p> I'm not sure if this is the same problem, but <a class="ext-link" href="http://groups.google.com/group/boost-list/browse_thread/thread/cc0f99ebade55cf3/ba8f563ea1f2f9fa?show_docid=ba8f563ea1f2f9fa"><span class="icon">​</span>my post to the mailing list</a> got no response. </p> <ol><li>The basic recipe: <div class="wiki-code"><div class="code"><pre><span class="n">filtering_ostream</span> <span class="n">out</span><span class="p">;</span> <span class="n">out</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">any_filter_at_all</span><span class="p">());</span> <span class="n">out</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="p">);</span> <span class="n">out</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Hello World!&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">flush</span><span class="p">;</span> <span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="c1">// Observe an empty console.</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">flush</span><span class="p">;</span> <span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="c1">// Observe printed text on console.</span> </pre></div></div></li><li>This problem is quite bad for me when doing the following on the command-line (for a more complicated program): <div class="wiki-code"><div class="code"><pre> ./program <span class="m">2</span>&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> tee some-file.log </pre></div></div>Because stdout is not getting flushed, the stdout and stderr get intermingled strangely. </li><li>However, disabling buffering on stdout works around the problem: <div class="wiki-code"><div class="code"><pre> stdbuf --output<span class="o">=</span><span class="m">0</span> ./program <span class="m">2</span>&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> tee some-file.log </pre></div></div></li></ol> Ticket anonymous Wed, 08 Sep 2010 19:57:00 GMT <link>https://svn.boost.org/trac10/ticket/4590#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4590#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/4590#comment:2" title="Comment 2">duncanphilipnorman@…</a>: </p> <blockquote class="citation"> <p> I've attached <a class="attachment" href="https://svn.boost.org/trac10/attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Attachment 'boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp' in Ticket #4590">boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp</a><a class="trac-rawlink" href="https://svn.boost.org/trac10/raw-attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Download">​</a>, which demonstrates (on Linux) that even <code>std::cout</code> does not get flushed by <code>filtering_ostream</code>. </p> </blockquote> <p> By the way, my test program is much less elegant than the original reporter's testcase. One must observe console output (based on timing due to <code>sleep()</code> calls) to see the problem, since I wasn't sure how to test <code>std::cout</code> otherwise. </p> </description> <category>Ticket</category> </item> <item> <author>Mike Tryhorn <miketryhorn@…></author> <pubDate>Fri, 24 Sep 2010 18:04:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4590#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4590#comment:4</guid> <description> <p> Dear all, </p> <p> I recently upgraded from Boost 1.43.0 to 1.44.0 and have experienced the same problem. My personal debug logging library relies upon the proper functioning of the flush (and sync) mechanism in boost::iostreams to produce transactional, orderly message output. Unfortunately, in the latest boost version this flush mechanism is non-functional. </p> <p> However, I've made an investigation of this problem by putting versions 1.43.0 and 1.44.0 side-by-side. I am relieved to say that I have tracked the problem, and have a simple solution. </p> <p> I have confirmed that this problem was introduced by the bugfix for <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/2356" title="#2356: Bugs: bug at compile time when using customized char_traits (closed: fixed)">#2356</a>, which changed the following code in boost/iostreams/detail/adapter/concept_adapter.hpp: </p> <div class="wikipage" style="font-size: 85%"><p> Boost v1.43.0 </p> <div class="wiki-code"><div class="code"><pre> <span class="kt">bool</span> <span class="nf">flush</span><span class="p">(</span> <span class="n">BOOST_IOSTREAMS_BASIC_STREAMBUF</span><span class="p">(</span><span class="n">char_type</span><span class="p">,</span> <span class="n">BOOST_IOSTREAMS_CHAR_TRAITS</span><span class="p">(</span><span class="n">char_type</span><span class="p">))</span><span class="o">*</span> <span class="n">sb</span> <span class="p">)</span> <span class="p">{</span> <span class="kt">bool</span> <span class="n">result</span> <span class="o">=</span> <span class="n">any_impl</span><span class="o">::</span><span class="n">flush</span><span class="p">(</span><span class="n">t_</span><span class="p">,</span> <span class="n">sb</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">sb</span> <span class="o">&amp;&amp;</span> <span class="n">sb</span><span class="o">-&gt;</span><span class="n">BOOST_IOSTREAMS_PUBSYNC</span><span class="p">()</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="n">result</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="p">}</span> </pre></div></div></div><div class="wikipage" style="font-size: 85%"><p> Boost v1.44.0 </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">Device</span><span class="o">&gt;</span> <span class="kt">bool</span> <span class="n">flush</span><span class="p">(</span> <span class="n">Device</span><span class="o">*</span> <span class="n">dev</span> <span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">any_impl</span><span class="o">::</span><span class="n">flush</span><span class="p">(</span><span class="n">t_</span><span class="p">,</span> <span class="n">dev</span><span class="p">);</span> <span class="p">}</span> </pre></div></div></div><p> (See changeset: <a class="ext-link" href="https://svn.boost.org/trac/boost/changeset/63034"><span class="icon">​</span>https://svn.boost.org/trac/boost/changeset/63034</a>.) </p> <p> For some reason, the 'PUBSYNC' operation was removed. I suspect that it was merely mistaken as being unnecessary, however it is the mechanism by which the filtering_ostream's chain is flushed in its entirety. </p> <p> To give some context: indirect_streambuf (the stream buffer used by filtering_ostream), being a std::streambuf, has a required 'sync' method: </p> <div class="wikipage" style="font-size: 85%"><p> boost::iostreams::indirect_detail::indirect_streambuf::sync </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Tr</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Mode</span><span class="o">&gt;</span> <span class="kt">int</span> <span class="n">indirect_streambuf</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">Tr</span><span class="p">,</span> <span class="n">Alloc</span><span class="p">,</span> <span class="n">Mode</span><span class="o">&gt;::</span><span class="n">sync</span><span class="p">()</span> <span class="p">{</span> <span class="k">try</span> <span class="p">{</span> <span class="c1">// sync() is no-throw.</span> <span class="n">sync_impl</span><span class="p">();</span> <span class="n">obj</span><span class="p">().</span><span class="n">flush</span><span class="p">(</span><span class="n">next_</span><span class="p">);</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> <span class="k">catch</span> <span class="p">(...)</span> <span class="p">{</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </pre></div></div></div><p> Where 'obj()' returns a 'concept_adapter&lt;T&gt;&amp;'. This 'sync' method's implementation has not changed between versions 1.43.0 and 1.44.0. This sync method is called by ostream::flush, and relies upon the expectation that any 'flush' will indeed itself perform a 'sync' operation (the aforementioned 'PUBSYNC'). </p> <div class="wikipage" style="font-size: 85%"><blockquote> <p> See: <a class="ext-link" href="http://www.cplusplus.com/reference/iostream/ostream/flush/"><span class="icon">​</span>http://www.cplusplus.com/reference/iostream/ostream/flush/</a> <br /> And: <a class="ext-link" href="http://www.cplusplus.com/reference/iostream/streambuf/pubsync/"><span class="icon">​</span>http://www.cplusplus.com/reference/iostream/streambuf/pubsync/</a> </p> </blockquote> </div><p> However, as 'PUBSYNC' has been removed from concept_adaptor&lt;T&gt;::sync, only the first device or filter in the filtering_ostream's chain will ever be flushed. This means that for any filtering_ostream which a chain of length 2 or more, the stream's output will only reach its destination when a buffer overflows, or the stream is released. </p> <p> So, I hope that by now the solution is self-evident: </p> <div class="wikipage" style="font-size: 85%"><p> Proposal for Boost 1.45.0 </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">Device</span><span class="o">&gt;</span> <span class="kt">bool</span> <span class="n">flush</span><span class="p">(</span> <span class="n">Device</span><span class="o">*</span> <span class="n">dev</span> <span class="p">)</span> <span class="p">{</span> <span class="kt">bool</span> <span class="n">result</span> <span class="o">=</span> <span class="n">any_impl</span><span class="o">::</span><span class="n">flush</span><span class="p">(</span><span class="n">t_</span><span class="p">,</span> <span class="n">dev</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">dev</span> <span class="o">&amp;&amp;</span> <span class="n">dev</span><span class="o">-&gt;</span><span class="n">BOOST_IOSTREAMS_PUBSYNC</span><span class="p">()</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="n">result</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="p">}</span> </pre></div></div></div><p> I've tested this solution with the test code provided both in this bug report (attachment: boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp), and <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/2356" title="#2356: Bugs: bug at compile time when using customized char_traits (closed: fixed)">#2356</a> (attachment: test.cpp). </p> <p> I'm not myself a boost contributor (this is my first contribution), so if you believe it to be correct, could someone please submit this change to SVN? Correction diff file to follow. </p> <p> Many thanks. </p> </description> <category>Ticket</category> </item> <item> <author>Mike Tryhorn <miketryhorn@…></author> <pubDate>Fri, 24 Sep 2010 18:06:06 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4590 https://svn.boost.org/trac10/ticket/4590 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_4590_correction.diff</span> </li> </ul> <p> Correction to concept_adapter.hpp for boost 1.44.0. </p> Ticket Duncan Exon Smith <duncanphilipnorman@…> Tue, 12 Oct 2010 21:56:03 GMT <link>https://svn.boost.org/trac10/ticket/4590#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4590#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/4590#comment:2" title="Comment 2">duncanphilipnorman@…</a>: </p> <blockquote class="citation"> <p> I've attached <a class="attachment" href="https://svn.boost.org/trac10/attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Attachment 'boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp' in Ticket #4590">boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp</a><a class="trac-rawlink" href="https://svn.boost.org/trac10/raw-attachment/ticket/4590/boost_iostreams_filtering_ostream_does_not_flush_at_all.cpp" title="Download">​</a>, which demonstrates (on Linux) that even <code>std::cout</code> does not get flushed by <code>filtering_ostream</code>. </p> </blockquote> <p> I believe my issue is distinct from the one described by the original poster -- particularly because my issue is present already in Boost 1.43.0. I have created a new ticket for my issue (see <a class="new ticket" href="https://svn.boost.org/trac10/ticket/4728" title="#4728: Bugs: &#34;iostreams::detail::mode_adapter&lt;&gt;&#34; is never &#34;flushable&#34;: flushing a ... (new)">#4728</a>), along with a patch to fix it. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Fri, 11 Feb 2011 16:18:38 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4590#comment:6 https://svn.boost.org/trac10/ticket/4590#comment:6 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/68779" title="Fix flush regression. Fixes #4590.">[68779]</a>) Fix flush regression. Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4590" title="#4590: Bugs: Flushing a filtering_ostream stopped working in Boost 1.44 (closed: fixed)">#4590</a>. </p> Ticket