Boost logo

Boost Users :

Subject: [Boost-users] file_descriptor_sink vs. pclose
From: Dan Stahlke (dstahlke_at_[hidden])
Date: 2010-05-05 23:05:08


I've been having difficulty using iostreams::file_descriptor_sink with
popen in Linux. The problem is that popen() requires a matching pclose()
rather than a close(). Now, file_descriptor_sink has a close_on_exit
flag that, when set to false, supposedly prevents it from calling close()
on the underlying file descriptor, but it calls close() anyway. Is this
a bug in boost or am I doing it wrong? As a workaround I can call flush
() on the iostream and then pclose() on the filehandle, but it seems like
it would be better to actually close the iostream.

I've tested the example below using boost 1.39 and using 1.43 from
subversion. The result in both cases is:
        pclose returned error (test A): Bad file descriptor
        pclose returned error (test B): Bad file descriptor
        Hello
        Hello

-------------------------

#include <stdexcept>
#include <iostream>

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>

#include <stdio.h>
#include <string.h>
#include <errno.h>

typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
        boost_stream;

int main() {
    bool close_on_exit = false;

    FILE *pout = popen("cat", "w");
    {
        boost_stream bs(fileno(pout), close_on_exit);
        bs << "Hello\n";
        // destructor calls close(fileno(pout))
    }
    if(pclose(pout)) {
        char *err = strerror(errno);
        std::cerr << "pclose returned error (test A): " << err <<
                        std::endl;
    }

    pout = popen("cat", "w");
    boost_stream bs(fileno(pout), close_on_exit);
    bs << "Hello\n";
    // bs.close() calls close(fileno(pout))
    // without the bs.close(), there would be no pclose() error
    bs.close();
    // If bs.close() is not used, bs.flush() can be used to flush data to
    // pipe before calling pclose().
    //bs.flush();
    if(pclose(pout)) {
        char *err = strerror(errno);
        std::cerr << "pclose returned error (test B): " << err <<
                        std::endl;
    }
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net