gpt4 book ai didi

c++ - 在超时的异步模式下使用升压进程运行进程

转载 作者:搜寻专家 更新时间:2023-10-31 02:05:00 25 4
gpt4 key购买 nike

在下面的代码中,我试图实现一个运行 shell 命令并获取 stdiostderr 和返回代码的程序。我正在按照建议在 async 模式下使用 boost process here .

namespace bp = boost::process;
class Process {

public:
Process(std::string & cmd, const int timeout);
void run();

private:
void timeout_handler();

const std::string command;
const int timeout;

bool killed;
bool stopped;

std::string stdOut;
std::string stdErr;
int returnStatus;

boost::asio::io_service ios;
boost::process::group group;
boost::asio::deadline_timer deadline_timer;
};

Process::Process(std::string & cmd, const int timeout):
command(cmd),
timeout(timeout),
deadline_timer(ios)
{}

void Process::timeout_handler()
{
if (stopped)
return;

if (deadline_timer.expires_at() <= boost::asio::deadline_timer::traits_type::now())
{
std::cout << "Time Up!" << std::endl;
group.terminate();
std::cout << "Killed the process and all its decendents" << std::endl;
killed = true;
stopped = true;
deadline_timer.expires_at(boost::posix_time::pos_infin);
}
deadline_timer.async_wait(std::bind(&Process::timeout_handler, this));
}

void Process::run()
{

std::future<std::string> dataOut;
std::future<std::string> dataErr;

bp::child c(command, bp::std_in.close(), bp::std_out > dataOut, bp::std_err > dataErr, ios, group);
deadline_timer.expires_from_now(boost::posix_time::seconds(timeout));
deadline_timer.async_wait(std::bind(&Process::timeout_handler, this));

ios.run();
c.wait();

stdOut = dataOut.get();
stdErr = dataErr.get();
returnStatus = c.exit_code();
}

int main(int argc, char** argv)
{
if(argc < 2)
{
std::cout << "Usage: \na.out <command>" << std::endl;
exit(1);
}
std::vector<std::string> arguments(argv + 1, argv + argc);

std::string command;
for( const auto & tok : arguments)
{
command += tok + " ";
}

std::cout << command << std::endl;
Process p(command, 10);
p.run();
return 0;
}

现在,上面的代码仅在 deadline_timer 到期后返回。我想要的是,如果子进程在计时器到期之前完成,则它应该退出,或者它(连同它派生的所有子进程)应该被终止。请指出我的代码中的错误。

最佳答案

错误确实很简单:你应该取消deadline timer!

io_service::run() 除非

否则不会返回
  1. 处理程序发出的异常
  2. 没有更多的工作排队。

当死线计时器正在进行时,这意味着不满足第二个条件。所以 io_service::run() 等待它,因为你要求它这样做。

其他说明:

  • 使用错误代码来检测定时器取消而不是实时比较
  • 无需循环链接计时器(事实上,这是在寻找 io_service 永远不会完成的错误)
  • 您的代码无法初始化 stoppedkilled

靠 Coliru 生存

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

namespace bp = boost::process;
class Process {

public:
Process(std::string &cmd, const int timeout);
void run();

private:
void timeout_handler(boost::system::error_code ec);

const std::string command;
const int timeout;

bool killed = false;
bool stopped = false;

std::string stdOut;
std::string stdErr;
int returnStatus = 0;

boost::asio::io_service ios;
boost::process::group group;
boost::asio::deadline_timer deadline_timer;
};

Process::Process(std::string &cmd, const int timeout) : command(cmd), timeout(timeout), deadline_timer(ios) {}

void Process::timeout_handler(boost::system::error_code ec) {
if (stopped)
return;

if (ec == boost::asio::error::operation_aborted)
return;

if (deadline_timer.expires_at() <= boost::asio::deadline_timer::traits_type::now()) {
std::cout << "Time Up!" << std::endl;
group.terminate(); // NOTE: anticipate errors
std::cout << "Killed the process and all its decendants" << std::endl;
killed = true;
stopped = true;
deadline_timer.expires_at(boost::posix_time::pos_infin);
}
//NOTE: don't make it a loop
//deadline_timer.async_wait(boost::bind(&Process::timeout_handler, this, boost::asio::placeholders::error));
}

void Process::run() {

std::future<std::string> dataOut;
std::future<std::string> dataErr;

deadline_timer.expires_from_now(boost::posix_time::seconds(timeout));
deadline_timer.async_wait(boost::bind(&Process::timeout_handler, this, boost::asio::placeholders::error));

bp::child c(command, bp::std_in.close(), bp::std_out > dataOut, bp::std_err > dataErr, ios, group,
bp::on_exit([=](int e, std::error_code ec) {
// TODO handle errors
std::cout << "on_exit: " << ec.message() << " -> " << e << std::endl;
deadline_timer.cancel();
returnStatus = e;
}));

ios.run();

stdOut = dataOut.get();
stdErr = dataErr.get();

c.wait();

returnStatus = c.exit_code();
}

int main(int argc, char **argv) {
if (argc < 2) {
std::cout << "Usage: \na.out <command>" << std::endl;
exit(1);
}
std::vector<std::string> arguments(argv + 1, argv + argc);

std::string command;
for (const auto &tok : arguments) {
command += tok + " ";
}

std::cout << command << std::endl;
Process p(command, 2);
p.run();
}

打印例如

 $ ./sotest 'echo hello'

echo hello
on_exit: Success -> 0

 $ ./sotest 'sleep 1'

sleep 1
on_exit: Success -> 0

 $ ./sotest 'sleep 3'

sleep 3
Time Up!
Killed the process and all its decendants
on_exit: Success -> 9

关于c++ - 在超时的异步模式下使用升压进程运行进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52624004/

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