gpt4 book ai didi

c++ - Boost.Process - 从具有 sleep 循环的进程中读取

转载 作者:太空宇宙 更新时间:2023-11-04 12:32:51 25 4
gpt4 key购买 nike

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

//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() 上挂起,可能是因为 sleeper 应用程序永远不会终止。但它应该读取 sleeper 的输出直到分隔符,所以我不知道这里有什么问题。我期待一些解释。

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

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

Note Child processes that use such C run-time functions as printf() and fprintf() can behave poorly when redirected. The C run-time functions maintain separate IO buffers. When redirected, these buffers might not be flushed immediately after each IO call. As a result, the output to the redirection pipe of a printf() call or the input from a getch() call is not flushed immediately and delays, sometimes-infinite delays occur. This problem is avoided if the child process flushes the IO buffers after each call to a C run-time IO function. Only the child process can flush its C run-time IO buffers. A process can flush its C run-time IO buffers by calling the fflush() function.

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

最佳答案

事实上,你的卧铺程序并没有终止。 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 行。

终止 child

你可以杀死它:

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"

关于c++ - Boost.Process - 从具有 sleep 循环的进程中读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57988900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com