- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在下面的代码中,我试图实现一个运行 shell 命令并获取 stdio
、stderr
和返回代码的程序。我正在按照建议在 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()
除非
当死线计时器正在进行时,这意味着不满足第二个条件。所以 io_service::run()
等待它,因为你要求它这样做。
其他说明:
stopped
和 killed
靠 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/
在 Java 中,我可以在不指定类型的情况下定义泛型类的变量。 class Tree> {} somewhere-else: Tree tree; 然后我可以从文件中读入一些对象并将其类型转换为我想要
我昨天发布了一个问题,我使用 multi_map 解决了这个问题: Having a composite key for hash map in c++ 这很有效,但是当数据足够大时就会出现问题。 我
这应该很简单(我只是在学习 boost,所以我错过了一些东西) 我已经使用 json_read 读取了一些简单的 JSON,现在有了一个 ptree。网络上的所有示例都显示使用 ptree.get("
所以我的问题很简单,在我的词法分析器类(扩展 lex::lexer )中,我有以下内容; this->self.add ... ("&&", AND_AND) ("||", O
关于这个问题有很多问题,但似乎没有一个能解决我的问题。我不认为这真的是一个 Boost::Variant 问题;我很确定我只是以错误的方式使用了模板。我能够剥离代码,以便您可以编译它并自己查看问题,这
这个问题确定不可复制类型不能与 Boost Variant 一起使用 树类 template class Tree{ private: class TreeNode{
我有一个用于解析标识符的解析器,如 foo, bar, baz 和一个用于解析嵌套标识符的解析器,如 foo::bar, foo::bar.baz, foo::bar.baz.baham它们都解析为相
通过阅读其他 Stack Overflow 条目和 boost::asio 文档,我确认没有同步 ASIO 读/写调用也提供易于使用的超时作为调用的参数。 我正在使用使用超时的 select(2) 调
我应该在我的 jamroot.jam 文件中放入什么,以便 libAPLibrary.so 与 MyProject 编译的结果相关联? root |-MyProject | |-jamroot
我有一个 vector,我想将其插入到一个 set 中。这是三个不同的调用之一(另外两个更复杂,涉及 boost::lambda::if_()),但解决这个简单的案例将帮助我解决其他问题。 std::
我确定套接字在我的应用程序中的任何地方都关闭了,并且我不断在我的/proc/pid/fd/下获取这个新创建的 fd/socket 文件,这是正常的。我确定不是。 connection.cpp con
元组是由括号括起来的逗号分隔列表,例如 () (,) (thing,) (2,3) 如果我有 #define ISTUPLE(x) \\... 我想要类似 ISTUPLE(nope) 的东西解析为 0
我有一个问题,两个线程是这样调用的,一个接一个。 new boost::thread( &SERVER::start_receive, this); new boost::thread( &SERVE
遇到 Boost 程序选项问题。我添加了一个多次使用选项,我们称之为“--opt”。当我从命令行使用两个“--opt”运行program.exe时,我从boost中收到以下错误。 terminatin
我想用类似于 C 的转义规则来解析字符串。我想保留转义,而不是解码它们然后重新编码。所以我认为 *(char_('\\') >> char_ | char_ - '"') 会做我想做的事,但事实并非如
聊天程序就是一个很好的例子。只需要一个可以接受来自客户端的多个连接的服务器,并且该服务器需要能够向各个客户端发送消息。 我计划将它变成一个分布式计算程序,以使用多个神经网络。 最佳答案 Asio是处理
我是一名优秀的程序员,十分优秀!