提升进程 running() 和 exit_code() 线程安全
Posted
技术标签:
【中文标题】提升进程 running() 和 exit_code() 线程安全【英文标题】:boost process running() and exit_code() thread safety 【发布时间】:2017-12-05 12:25:11 【问题描述】:我正在使用boost::process::child
和boost::process::async_pipe
启动应用程序并异步读取(通过boost::asio
)应用程序在发生这种情况时在屏幕上输出的所有内容。
我还想使用child::running()
方法检查应用程序是否处于活动状态;如果没有运行,我想使用child::exit_code
读取退出代码。
这是非常有用的特别是,因为它是一种通知应用程序崩溃或意外退出的方法(我找不到更好的方法);当应用程序退出时,将调用回调并设置boost::system::error_code
。
你知道我是否可以在async_pipe::async_read_some
调用的回调中使用这两个方法吗?
一般来说,更简单的问题是 child::running()
和 child::exit_code()
是否是线程安全的(在 Windows 和 Linux 中)。
namespace bp = boost::process;
char my_buffer[1024];
boost::asio::io_service io;
bp::async_pipe in_pipe(io);
void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred);
void schedule_read()
in_pipe.async_read_some(
boost::asio::buffer(my_buffer),
boost::bind(&handle_pipe_read,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
void handle_pipe_read(
const boost::system::error_code &ec,
std::size_t bytes_transferred
)
// Q: Is this call possible? 'handle_pipe_read' can run in any thread
if(c->running())
std::cout << "I am alive" << std::endl;
else
std::cout << "EXIT CODE:" << c->exit_code() << std::endl;
if(ec) return; //app probably exit
// Do something with buffer and re-schedule
schedule_read();
int main()
bp::child c("my_program_url", bp::std_out > in_pipe);
any_c = &c;
schedule_read();
io.run();
【问题讨论】:
【参考方案1】:由于您只在主线程上运行io_service::run()
,所有完成处理程序也在那里运行。没有线程。
记得将 io_service 传递给孩子,并使用 on_exit
处理程序:
Live On Coliru
#include <boost/process.hpp>
//#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <system_error>
#include <utility>
#include <iostream>
namespace bp = boost::process;
char my_buffer[1024];
boost::asio::io_service io;
bp::async_pipe in_pipe(io);
void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred);
void schedule_read()
in_pipe.async_read_some(
boost::asio::buffer(my_buffer),
boost::bind(&handle_pipe_read, _1, _2));
void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred)
if (ec)
return; // app probably exit
// Do something with buffer and re-schedule
std::cout.write(my_buffer, bytes_transferred);
if (in_pipe.is_open())
schedule_read();
int main()
bp::child c("/bin/ls", bp::std_out > in_pipe,
bp::on_exit([](int code, std::error_code ec)
std::cout << "Child exited (" << code << "): " << ec.message() << std::endl;
in_pipe.close();
), io);
schedule_read();
io.run();
std::cout << "Service done (" << c.exit_code() << ")" << std::endl;
打印:
a.out
main.cpp
Child exited (0): Success
Service done (0)
【讨论】:
这是一个我不知道的可爱功能。让我检查一下,我会回来找你的。 有一个问题要问你,以防万一:你知道这个 boost::process::on_exit 在哪里执行吗?它是一个可以在任何线程中执行的回调吗,就像所有 boost::asio 处理程序一样? 经过测试,我还可以看到,如果子应用程序崩溃,则不会调用此处理程序……所以我仍然不确定收到崩溃通知的最佳方式是什么……如果应用程序未运行且未正确终止,也可能使用 wait() 引发异常, 我在第一句话中告诉过你:它是一个完成处理程序,在服务线程上调用(运行io_service::run()
的线程)。如果您有多个线程在运行您的服务,那么您不知道是哪一个(所以使用 strands 并将 pipe-close 发布回服务)
@AbruzzoForteeGentile 我希望on_exit
被称为boost.org/doc/libs/master/doc/html/boost/process/on_exit.html【参考方案2】:
对我有用的唯一解决方案是以下
-
安排完成读取
始终检查呼叫
child::running()
在设置错误代码时不要重新安排
当管道损坏(由于崩溃)时,读取的完成处理程序会将 boost::error_code 参数设置为 true。尽管如此,当 boost::error_code 未设置时,我也看到 child::running() 为 false 的情况。
【讨论】:
以上是关于提升进程 running() 和 exit_code() 线程安全的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核进程管理 ( Linux 内核中的进程状态 | TASK_RUNNING | TASK_INTERRUPTIBLE | __TASK_STOPPED | EXIT_ZOMBIE )
linux下的进程管理(进程的基本了解及查看pstree,ps,pgrep命令)
启动zookeeper时,jps显示有进程,但是status查看状态时就Error contacting service. It is probably not running