【问题标题】:boost::process::child will not exit after closing input streamboost::process::child 在关闭输入流后不会退出
【发布时间】:2020-06-15 11:08:38
【问题描述】:

在以下示例中,我尝试将一些数据写入子进程,该子进程处理数据并将其写入文件。关闭流后,父进程无限期地等待子进程完成。我不知道如何表明我已经完成了数据的写入,并且希望子进程停止读取并完成它正在做的任何事情。根据调用 terminate would send a SIGKILL 的文档,我认为这不是我想要的。

我错过了什么?我检查了this question,但我宁愿先尝试使实际代码与同步 IO 一起工作。

#include <boost/process.hpp>
#include <iostream>


namespace bp = boost::process;


int main(int argc, char **argv)
{
    boost::process::opstream in{};
    boost::process::child child("/path/to/test.py", bp::std_in < in);

    in << "test1\n";
    in << "test2\n";
    in << "test3\n";
    in << std::flush;

    std::cerr << "Closing the stream…\n";
    in.close();
    std::cerr << "Waiting for the child to exit…\n";
    child.wait(); // Parent seems to hang here.

    return 0;
}

test.py 只是将数据写入文件,如下所示:

#!/usr/local/homebrew/opt/python@3.8/bin/python3

import sys

with open("/tmp/test.txt", "w") as f:
    for line in sys.stdin:
        f.write(line)

【问题讨论】:

    标签: c++ boost boost-process


    【解决方案1】:

    查看源代码后,我发现至少在这种情况下关闭流并没有关闭关联的管道。手动执行此操作确实解决了问题:

    ...
    in.close();
    in.pipe().close();
    child.wait(); // Does not hang.
    

    【讨论】:

      【解决方案2】:

      文档警告说,对子进程使用同步 IO 容易出现死锁。

      以下是对异步 IO 的最小改写:

      #include <boost/process.hpp>
      #include <iostream>
      
      namespace bp = boost::process;
      
      int main() {
          boost::asio::io_context ioc;
          bp::async_pipe in{ioc};
          bp::child child("./test.py", bp::std_in < in, bp::std_out.close());
      
          for (auto msg : { "test1\n", "test2\n", "test3\n" }) {
              write(in, bp::buffer(msg, strlen(msg)));
          }
      
          std::cerr << "Closing the pipe…\n";
          in.close();
          std::cerr << "Waiting for the child to exit…\n";
          ioc.run(); // already awaits completion
      
          child.wait(); // Parent seems to hang here.
      }
      

      你可以做一些延迟让它更现实:

      #include <boost/process.hpp>
      #include <iostream>
      
      using namespace std::chrono_literals;
      namespace bp = boost::process;
      
      int main() {
          boost::asio::io_context ioc;
          bp::async_pipe in{ioc};
          bp::child child("./test.py", bp::std_in < in, bp::std_out.close());
      
          std::thread th([&] {
              for (auto msg : { "test1\n", "test2\n", "test3\n" }) {
                  write(in, bp::buffer(msg, strlen(msg)));
                  std::this_thread::sleep_for(1s);
              }
      
              std::cerr << "Closing the pipe…\n";
              in.close();
          });
      
          std::cerr << "Waiting for the child to exit…\n";
          ioc.run(); // already awaits completion
          th.join();
      
          child.wait(); // Parent seems to hang here.
      }
      

      对于成熟的异步 IO,请参阅其他示例:

      【讨论】:

      • 感谢您的详尽回答!实际上我刚才发现问题是由a pipe not being closed引起的。我会看看我的解决方案是否有效,然后可能会联系开发人员以确认这是预期的行为。
      • 我很确定是这样,因为过去我已经多次看到这种行为发生变化/被修复。我觉得它需要更好的文档。
      猜你喜欢
      • 1970-01-01
      • 2020-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      相关资源
      最近更新 更多