Skip to content

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

@ednolan

Description

@ednolan

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions