boostorg/iostreams

No way to detect the return code of pubsync() during close()

Opened this issue · 0 comments

This program completes successfully despite the fact that it failed to write any data:

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <fstream>

int main() {
  std::ofstream s{"/dev/full"};
  boost::iostreams::filtering_ostream filtering{};
  filtering.push(boost::iostreams::gzip_compressor{});
  filtering.push(s);
  filtering << "Hello, world!";
  boost::iostreams::close(filtering);
  // at this point, s.good() is true
}

Debugging reveals that inside of close(), a call to pubsync() has indicated an error flushing out the data. This error is noticed by boost::iostreams's flush implementation (flush.hpp:65):

template<>
struct flush_device_impl<ostream_tag> {
    template<typename T>
    static bool flush(T& t)
    { return t.rdbuf()->BOOST_IOSTREAMS_PUBSYNC() == 0; }
};

But flush's result is ignored inside of the close() implementation (close.hpp:170):

    template<typename T>
    static void close(T& t, BOOST_IOS::openmode which)
    {
        if (which == BOOST_IOS::out)
            iostreams::flush(t);
    }

Since the compressing filters are not flushable, the only way to flush them is to close them; since this error is ignored on close, there appears to be no way in the API to discover this form of write failure when a compressing filter is in the chain.

There should be a way to avoid ignoring this error. Maybe close should throw if the call to iostreams::flush fails.