1

我有一定的问题,我不确定我做错了什么。

//sleeper.exe

int main()
{
  int i = 0;
  while (true)
  {
    printf("%i\n", ++i);
    sleep_for(1s);
  }

  return 0;
}

我想在我的应用程序中捕获 sleeper 的输出并将其逐行添加到某个容器中;

//application.exe

int main()
{
  io_context context;
  async_pipe out(context);
  child sleeper("sleeper.exe", std_out > out, context);      

  vector<string> lines;
  streambuf buffer;
  async_read_until(out, buffer, '\n', [](const error_code& code, size_t size)
  {
    // Add line to container
  });

  context.run();

  return 0;
}

不幸的是,我的应用程序挂起context.run(),可能是因为睡眠应用程序永远不会终止。但它应该读取睡眠者的输出直到分隔符,所以我不知道这里有什么问题。我期待着一些解释。

在对主题进行更多研究后进行编辑:

根据: https: //support.microsoft.com/en-us/help/190351/how-to-spawn-console-processes-with-redirected-standard-handles

注意 使用诸如 printf() 和 fprintf() 之类的 C 运行时函数的子进程在重定向时可能表现不佳。C 运行时函数维护单独的 IO 缓冲区。重定向时,这些缓冲区可能不会在每次 IO 调用后立即刷新。因此,printf() 调用的重定向管道的输出或 getch() 调用的输入不会立即刷新,并且会出现延迟,有时甚至是无限延迟。如果子进程在每次调用 C 运行时 IO 函数后刷新 IO 缓冲区,则可以避免此问题。只有子进程可以刷新其 C 运行时 IO 缓冲区。进程可以通过调用 fflush() 函数刷新其 C 运行时 IO 缓冲区。

我仍在寻找该领域的解决方案。

4

1 回答 1

0

事实上,你的卧铺程序不会终止。run()将运行到完成。

让我们首先让示例“真实”,以便它有一个实际的读取循环来读取超过 1 行:

std::vector<std::string> lines;

boost::asio::streambuf buffer;

std::function<void()> read_loop;
read_loop = [&] {
    boost::asio::async_read_until(out, buffer, "\n", [&](boost::system::error_code code, std::size_t size) {
        if (code) {
            std::cerr << "Oops: " << code.message() << std::endl;
        } else {
            std::cerr << "received: " << size << " bytes" << std::endl;

            auto b = buffers_begin(buffer.data()), m = b+size;
            lines.emplace_back(b, m);

            buffer.consume(size);

            if (lines.size()<10) {
                read_loop();
            }
        }
    });
};

read_loop();

context.run();

您可以看到它尝试读取 10 行。

终止孩子

你可以杀死它:

if (lines.size()<10) {
    read_loop();
} else {
    c.terminate();
}

或关闭输出管道,导致相同(断管):

if (lines.size()<10) {
    read_loop();
} else {
    out.close();
}

德诺

我无法让它在 Coliru 上运行,但我将 first.exe 替换为:

#include <iostream>
#include <chrono>
#include <thread>
#include <random>

using namespace std;
static mt19937 prng{random_device{}()};
static auto l() { return uniform_int_distribution(5,20)(prng); }
static auto c() { return uniform_int_distribution('a','z')(prng); }

int main() {
    while(true) {
        cout << std::string(l(), c()) << endl;
        this_thread::sleep_for(chrono::seconds(1));
    }
}

并通过上述程序,完整:

#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <iomanip>
#include <regex>

int main() {
    namespace bp = boost::process;
    using namespace std::string_literals;
    boost::asio::io_context context;
    bp::async_pipe out(context);

    bp::child c("./first.exe", bp::std_out > out, context);

    std::vector<std::string> lines;

    boost::asio::streambuf buffer;

    std::function<void()> read_loop;
    read_loop = [&] {
        boost::asio::async_read_until(out, buffer, "\n", [&](boost::system::error_code code, std::size_t size) {
            if (code) {
                std::cerr << "Oops: " << code.message() << std::endl;
            } else {
                std::cerr << "received: " << size << " bytes" << std::endl;

                auto b = buffers_begin(buffer.data()), m = b+size;
                lines.emplace_back(b, m);

                buffer.consume(size);

                if (lines.size()<10) {
                    read_loop();
                } else {
                    c.terminate();
                }
            }
        });
    };

    read_loop();
    context.run();

    for (auto& line : lines) {
        std::cout << std::quoted(std::regex_replace(line, std::regex("\\n"), "\\n"s)) << "\n";
    }

    return c.exit_code();
}

在我的系统上打印:

received: 19 bytes
received: 12 bytes
received: 20 bytes
received: 16 bytes
received: 6 bytes
received: 6 bytes
received: 20 bytes
received: 13 bytes
received: 16 bytes
received: 21 bytes
"dddddddddddddddddd\\n"
"lllllllllll\\n"
"jjjjjjjjjjjjjjjjjjj\\n"
"uuuuuuuuuuuuuuu\\n"
"yyyyy\\n"
"wwwww\\n"
"hhhhhhhhhhhhhhhhhhh\\n"
"qqqqqqqqqqqq\\n"
"aaaaaaaaaaaaaaa\\n"
"xxxxxxxxxxxxxxxxxxxx\\n"
于 2019-09-18T11:19:34.730 回答