Reading from boost::asio::readable_pipe used by Boost Process V2 ends with wrong code 109 on Windows (as opposed to expected boost::asio::error::eof)

Open
#553 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
cpp

Research direction

Run the complete example from the issue on Windows and Linux, then compare boost::asio::readable_pipe with synchronous read, asynchronous read, and co_await reads. Trace the Boost.Process V2 stdio connection and Asio pipe completion behavior. Done means Windows reaches the same EOF condition as Linux across the listed read forms, or the issue clearly documents an OS-independent workaround.

Written by the indexing model from the issue text.

Description

When I launch process (V2) and connect boost::asio::readable_pipe to its stdout on Windows, reading the pipe in a loop finishes with boost::system::error_code with value 109 and message "The pipe has been ended". On Linux I get code 2 and message "End of file". I would expect the code on Windows to behave the same way as Linux, as there seems to be a predefined constant for that: boost::asio::error::eof. This issue seems to be present in all functions (sync read, async read, async read with co_await).

What is the suggested workaround around this bug for now? Do I have to compare error codes based on OS, or is there something better and less error-prone?

Complete example:

#include <iostream>
#include <string>
#include <thread>
#include <vector>

#include <boost/asio.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/process/v2/process.hpp>
#include <boost/process/v2/stdio.hpp>

int main()
{
    boost::asio::io_context ctx;
    boost::asio::readable_pipe stdOutPipe(ctx);

#ifdef unix
    std::string processName = "/usr/bin/bash";
    std::vector<std::string> processArgs = { "-c", "ls", "-al"};
#else
    std::string processName = std::format("{}\\system32\\cmd.exe", std::getenv("windir"));
    std::vector<std::string> processArgs = { "/c", "dir"};
#endif

    boost::process::v2::process process(ctx, processName, processArgs, boost::process::v2::process_stdio{ {}, stdOutPipe, {} });

    std::jthread printStdOutThread([&]
        {
            while (true)
            {
                std::string stdOut;
                boost::system::error_code ec;
                size_t stdOutLength = boost::asio::read(stdOutPipe, boost::asio::dynamic_buffer(stdOut), ec);

                if (stdOutLength > 0)
                {
                    if (stdOut.size() != stdOutLength)
                        stdOut.resize(stdOutLength);

                    std::cout << stdOut;
                    std::cout.flush();
                }

                if (ec.value() != boost::system::errc::success)
                {
                    std::cout
                        << "------------------------\n"
                        << "Pipe end.\n"
                        << "eof: " << (ec == boost::asio::error::eof) << "\n"      // Windows: 0, Linux: 1
                        << "error code: " << ec.value() << "\n"       // Windows: 109, Linux: 2
                        << "error message: " << ec.message() << "\n"     // Windows: "The pipe has been ended", Linux: "End of file"
                        << "pipe is still open: " << stdOutPipe.is_open() << "\n"     // Windows: 1, Linux: 1
                        << "process is still running: " << process.running() << "\n";    // Unreliable because the child process may crash or be terminated at any time, but got this: Windows: false, Linux: true
                    std::cout.flush();

                    break;
                }
            }
        });

    ctx.run();

    int resultCode = process.wait();

    return resultCode;
}

Dominant language
C++
Stars
145
Forks
151
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from boostorg/process

All issues in boostorg/process

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.