我稍微更改了here找到的示例,以从在 main 中定义的单个 io_context 对象运行所有进程,并传递给每个任务,从不同的线程运行。
我期望所有任务都能成功完成,因为它们所花费的时间应该少于超时时间。但是,我的所有任务都超时了。知道为什么吗?
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <iostream>
using duration = std::chrono::system_clock::duration;
namespace asio = boost::asio;
using namespace std::chrono_literals;
std::string ExecuteProcess(boost::filesystem::path exe,
std::vector<std::string> args, //
duration time, //
std::error_code& ec,
asio::io_context& ioc) {
namespace bp = boost::process;
std::future<std::string> data, err_output;
bp::group g;
bp::child child(exe, args, ioc, g, bp::error(ec),
bp::std_in.null(), //
bp::std_out > data, //
bp::std_err > err_output);
if (std::error_code ignore; child.running()) {
g.terminate(ignore);
}
if (data.wait_for(time) == std::future_status::ready) {
ec.clear();
return data.get();
}
ec = make_error_code(asio::error::timed_out);
return {};
}
int main() {
constexpr duration timeout = 20ms;
constexpr auto script2 = "sleep 0.00005; echo -n 'Hello world'";
constexpr auto script1 = "/usr/bin/curl http://httpbin.org/ip -m 5";
asio::io_context ioc;
boost::asio::detail::thread_group collect_threads;
for (int i = 0 ; i < 20 ; i++) {
collect_threads.create_thread([&]() {
std::error_code ec_;
auto s = ExecuteProcess("/bin/bash", {"-c", script2}, timeout, ec_, ioc);
std::cout << "got " << ec_.message() << ": " << s << std::endl;
});
}
ioc.run();
}
附言: 对于超时实现,我也在考虑使用
result = waitpid(pid, &status, WNOHANG)
而不是 std::future
。
然而,当我完成等待并且进程标准输出似乎正确时,检查child.exit_code()
返回383,这意味着该进程仍在运行 - 不知道为什么。
线程创建需要时间,您的
ioc.run()
在线程开始使用 io_context
之前执行,因此 run()
会立即返回。
这可能是您想要的:
boost::asio::io_context ctx;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> workGuard(ctx.get_executor());
ctx.run();
如果您想要
workGuard.reset()
停止,请在其他线程上调用 io_context::run()
。