Reading from pipe blocks for other processes on windows

Open
#417 3 comments 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
Stale
Tech stack
cpp

Research direction

Reproduce the example on Windows with Boost.Process 1.86, starting from the pipe setup and child wait in main.cpp. Inspect how bp::ipstream and bp::std_out handle each child process, then verify that each process's output is logged when that process finishes rather than after all processes complete.

Written by the indexing model from the issue text.

Description

Hey, maybe I'm doing something wrong but I can't get the pipes to read correctly with the following example:

The output is something like this:

[2024-10-29 21:16:11.569] [info] [main.cpp:41] Started both processed
[2024-10-29 21:16:11.584] [info] [main.cpp:18] Finished process: echo "hello" (0)
[2024-10-29 21:16:11.584] [info] [main.cpp:18] Finished process: false (1)
[2024-10-29 21:16:21.593] [info] [main.cpp:29] Output: 
[2024-10-29 21:16:21.593] [info] [main.cpp:29] Output: hello
[2024-10-29 21:16:21.596] [info] [main.cpp:18] Finished process: sleep 10.0 (0)
[2024-10-29 21:16:21.596] [info] [main.cpp:29] Output: 
[2024-10-29 21:16:21.597] [info] [main.cpp:47] Both processes finished successfully

NOTE: that the output: is only printent after ALL processes finish, which I don't understand because the pipe should've been closed when each individual process ends. I used boost process 1.86 (latest)

#include <boost/process.hpp>
#include <future>
#include <spdlog/spdlog.h>

namespace bp {
using namespace boost::process;
}

int main(int argc, char **argv) {
  try {
    auto run_child = [](const std::string &command) {
      try {
        bp::ipstream pipe_stream;
        {
          // Redirect stdout to our pipe
          bp::child c(command, bp::std_out > pipe_stream);
          c.wait();
          SPDLOG_INFO("Finished process: {} ({})", command, c.exit_code());
        } // child destructor runs here, closing its end of the pipe

        // Read the entire output from the pipe
        std::string output;
        std::string line;
        while (std::getline(pipe_stream, line)) {
          if (!output.empty()) output += "\n";
          output += line;
        }

        SPDLOG_INFO("Output: {}", output);
        return true;
      } catch (const std::exception &e) {
        SPDLOG_ERROR("Exception in child: {}", e.what());
        return false;
      }
    };

    auto future0 = std::async(std::launch::async, run_child, "sleep 10.0");
    auto future1 = std::async(std::launch::async, run_child, "false");
    auto future2 = std::async(std::launch::async, run_child, "echo \"hello\"");

    SPDLOG_INFO("Started both processed");

    bool result0 = future0.get();
    bool result1 = future1.get();

    if (result0 && result1) {
      SPDLOG_INFO("Both processes finished successfully");
    } else {
      SPDLOG_ERROR("One or both processes failed");
    }

  } catch (std::exception &e) {
    SPDLOG_ERROR("Exception: {}", e.what());
  }
  return 0;
}
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.