将 fork() 与 boost::asio::ip::tcp::iostream 一起使用是不是安全?
Posted
技术标签:
【中文标题】将 fork() 与 boost::asio::ip::tcp::iostream 一起使用是不是安全?【英文标题】:Is it safe to use fork() with boost::asio::ip::tcp::iostream?将 fork() 与 boost::asio::ip::tcp::iostream 一起使用是否安全? 【发布时间】:2012-12-25 00:11:24 【问题描述】:我正在尝试守护一个简单的 TCP 客户端,尽管客户端在前台工作得很好,但守护它会导致奇怪的行为。
作为一个测试用例,我有一个服务器,一旦您连接并发送一条消息(“已连接”),它将向您发送每秒连接一次的秒数。
如果我进行守护进程(通过调用 Test::Connect(true)
),连接会在任意时间后断开,即使在成功接收到几个数字后也是如此。
如果我不进行守护进程(通过调用 Test::Connect(false)
),连接将保持活动状态,并且我会继续按预期接收号码。
#include <string>
#include <iostream>
#include <boost/asio.hpp>
#include <unistd.h>
class Test
public:
Test()
io = nullptr;
void Connect(bool daemonize)
io = new boost::asio::ip::tcp::iostream("localhost", "6500");
if ( io && *io )
*io << "connected" << std::endl;
if ( daemonize )
pid_t child = fork();
if ( child < 0 ) exit(EXIT_FAILURE);
else if ( child > 0 ) exit(EXIT_SUCCESS);
umask(0);
if ( setsid() < 0 ) exit(EXIT_FAILURE);
if ( chdir("/tmp") < 0 ) exit(EXIT_FAILURE);
child = fork();
if ( child < 0 ) exit(EXIT_FAILURE);
else if ( child > 0 ) exit(EXIT_SUCCESS);
std::string line;
while ( *io )
std::getline(*io, line);
std::cout << "Line (" << line.length() << "): " << line << std::endl;
delete io;
io = nullptr;
private:
boost::asio::ip::tcp::iostream *io;
我完全不知道什么可能会提前切断输入流(看起来循环退出是因为io->eof() == true
和(bool)*io == false
)。由于这只发生在尝试守护进程时,我应该完全避免分叉吗?有没有更好的方法以编程方式将进程发送到后台(仅使用 C/C++ 代码)?
【问题讨论】:
【参考方案1】:我不确定这是否相关,但您是否需要在此处致电notify_fork
,例如:
boost::asio::io_service io_service;
// ...
if ( daemonize )
io_service.notify_fork(boost::asio::io_service::fork_prepare);
pid_t child = fork();
if (child == 0) io_service.notify_fork(boost::asio::io_service::fork_child);
else io_service.notify_fork(boost::asio::io_service::fork_parent);
// ...
【讨论】:
如果分叉需要io_service
吗?我可能弄错了,但我一直认为io_service
是用于异步代码的。
我不知道,但可能值得一试。
编辑中给出的io_service_
对象似乎没有绑定到任何东西;由于class Test
描述了一个客户端(同步使用tcp::iostream
),我对使用io_service
的相关性感到困惑。通过使用带有io_service
的异步调用来使用tcp::iostream
分叉是唯一正确的方法吗?
我提到调用 io_service::notify_fork 的唯一原因是因为在使用 boost::asio
时 fork
ing 时它看起来像是适当工作流程的一部分。您正在使用boost::asio
,即使它是在同步上下文中,所以我认为它可能值得一试。 :)
这样做没有产生明显的效果。稍微阅读notify_fork
,我注意到它主要用于每个客户端进程有效的服务器上下文中 - 与我试图实现的效果分开。以上是关于将 fork() 与 boost::asio::ip::tcp::iostream 一起使用是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章