Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does boost::process crash on Windows when stderr is redirected to a pipe?

Tags:

c++

windows

boost

This code based on boost::process 1.65.1 samples with some spelling errors fixed:

#include <boost/process.hpp>

int main(int argc, char *argv[])
{
    boost::asio::io_service ios;
    std::future<std::vector<char>> output, error;
    boost::process::child c("hostname.exe",
        boost::process::std_out > output,
        boost::process::std_err > boost::process::null,
        ios);
    ios.run();
    c.wait();
    if (output.valid())
    {
        auto processOutput = output.get();
        processOutput.push_back('\0');
        printf(processOutput.data());
    }
    if (error.valid())
    {
        auto processError = error.get();
        processError.push_back('\0');
        printf(processError.data());
    }
    return 0;
}

It works as expected. It runs hostname.exe and prints its output, i. e. your computer network name.

You probably see that error variable is unused. It is logical to read also stderr, even hostname.exe doesn't use it usually, realistic child process may of course use it. It looks trivial to just replace boost::process::std_err > boost::process::null with boost::process::std_err > error. However, it results in crash. The error message follows:

vector iterator not dereferencable

Does anyone know the reason and how to bypass this bug?

like image 854
Vitalii Avatar asked Nov 29 '17 13:11

Vitalii


1 Answers

It is a bug in Boost Process. The crash appears at include\boost\process\detail\windows\async_out.hpp The code that causes crash follows:

arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());

It is not important whether we redirect std_err or std_out. The problem appears when stream doesn't generate any output. For hostname.exe it is std_err, however, if you will try to run pyw.exe, you'll get this error for std_out also.

When progam generates no output, buffer->size() returns 0, so the vector becomes an empty one. And it looks like attempt to dereference an empty vector results in crash (debug assertion) at Visual C++.

The fix follows:

auto bufferSize = buffer->size();
if (bufferSize) {
    arg.resize(buffer->size());
    is.read(&*arg.begin(), buffer->size());
}

I didn't submit this bug report to boost, if anyone has time, lets he does it.

like image 59
Vitalii Avatar answered Oct 24 '22 07:10

Vitalii