Opened 12 years ago

#4807 new Bugs

Sink devices "leacks" exception out of the stream

Reported by: artyomtnk@… Owned by: Jonathan Turkanis
Milestone: To Be Determined Component: iostreams
Version: Boost 1.44.0 Severity: Problem
Keywords: Cc:

Description

I implement the sink device that sometimes may fail on writes. When Sink is implemented it should throw an exception on fault to notify the stream on error.

However it is not always works this way. I've got the exception to "leak" to the main program when I combine in the filter gzip_comressor() filter that writes to output device that its Sink is full. When I call reset on the filter the exception in leaking to the program instead of being caught.

On the other hand, if I don't throw but rather return 0, I get into infinite loop in the boost::iostreams::non_blocking_adapter::write when I call filter.reset().

In following example the exception is caught when filter.reset() is called, when it shouldn't.

    #include <boost/iostreams/stream.hpp>
    #include <boost/iostreams/filtering_stream.hpp>
    #include <boost/iostreams/filter/gzip.hpp>
    #include <boost/iostreams/tee.hpp>
    #include <iostream>

    class my_small_device : public boost::iostreams::sink
    {
        int count;
    public:
        my_small_device() : count(1000) {}
        std::streamsize write(char const *d,std::streamsize n)
        {
            if(count < n)
                throw std::runtime_error("Device is full");
            count-=n;
            return n;
        }
    };

    int main()
    {
        try {
            using namespace boost::iostreams;
            boost::iostreams::stream<my_small_device> output(my_small_device(),10);
            {
                boost::iostreams::filtering_ostream filter;
                filter.push(gzip_compressor());
                filter.push(output);
                for(int i=0;i<10000000;i++) {
                    if(!(filter << i << '\n')) {
                        std::cerr << "Fail!" << std::endl;
                        break;
                    }
                }
                std::cout << "Closing filter" << std::endl;
                filter.reset();
            }

            std::cout << "ok" << std::endl;
            return 0;
        }catch(std::exception const &e) {
            std::cerr << "Catched " << e.what() << std::endl;
            return 1;
        }
    }

Change History (0)

Note: See TracTickets for help on using tickets.