在Linux中使用fork()+execlp和boost::asio时出现地址重用错误
address reuse error when using fork() + execlp with boost::asio in Linux
我有一个程序,它在TCP端口上侦听特定字符串,并使用execlp
调用启动应用程序。我正在执行fork()
,以便在此execlp
调用之前启动子进程。启动后,父进程再次开始在同一端口上侦听。我正在关闭子进程中的套接字。
我已经在boost::asio::tcp_socket
上编写了一个包装器,在绑定套接字之前,我将addr_reuse
选项设置为true
。
现在,我的问题是在Linux中,在应用程序启动几次后,我得到了一个地址重用错误。在我的程序中,它不断尝试接受连接(或者更准确地说,尝试调度对boost::asio::io_service
的接受),直到绑定并接受成功。所以我收到了这个循环中的错误。
奇怪的是,如果我关闭(或终止)启动的可执行文件,则此错误停止出现,这意味着bind
成功。我确信,在启动的应用程序中,同一端口不会在任何地方使用。我正在使用异步套接字操作。知道我为什么会犯这个错误吗?
以下是我在套接字上接受的方式:(在开始新的接受之前,我还会在boost::asio::tcp_socket(_tcpSocket)
共享指针上调用reset。)
boost::asio::ip::tcp::endpoint endPoint(boost::asio::ip::tcp::v4(), port);
_acceptor.reset ( new boost::asio::ip::tcp::acceptor( *_ioService.get() ) );
_acceptor->open( endPoint.protocol() );
_acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
boost::system::error_code ec;
_acceptor->bind(endPoint, ec);
if ( ec.value() != boost::system::errc::success )
{
ec.clear();
_acceptor->close(ec);
close();
return false;
}
ec.clear();
_acceptor->listen(boost::asio::socket_base::max_connections, ec);
if ( ec.value() != boost::system::errc::success )
{
return false;
}
_acceptor->async_accept(*_tcpSocket,
boost::bind(&TCPSocket::_handleAsyncAccept,
this,
boost::asio::placeholders::error) );
以下是我的分叉方式:
pid_t pid = fork();
switch (pid)
{
case 0:
{
/// close all sockets for child process. as it might cause addr reuse error in parent process
_asyncNO->closeAll();
std::string binary = "<binaryName>";
std::string path = "<binaryPath>";
if ( execlp( path.c_str(), binary.c_str(), controllerIP.c_str(), (char *)0 ) == -1 )
{
LOG_ERROR("System call failed !!")
}
}
break;
default:
}
为了简单起见,我删除了日志记录。
正如@TannerSansbury在评论中所说,这可能是因为Boost.Asio需要通知fork()
:
关于Boost.Asio.分叉的最新版本文档
此处转载的相关章节:
Boost.Asio支持使用
fork()
系统调用的程序。如果程序在适当的时间调用io_service.notify_fork()
,Boost.Asio将重新创建任何内部文件描述符(例如用于唤醒反应堆的"self-pipe-trick"描述符)。通知通常如下执行:
io_service_.notify_fork(boost::asio::io_service::fork_prepare);
if (fork() == 0)
{
io_service_.notify_fork(boost::asio::io_service::fork_child);
// ...
}
else
{
io_service_.notify_fork(boost::asio::io_service::fork_parent);
// ...
}
用户定义的服务也可以通过重写
io_service::service::fork_service()
虚拟函数来实现fork-aware。请注意,通过Boost.Asio的公共API可访问的任何文件描述符(例如
basic_socket<>
、posix::stream_descriptor
等的底层描述符)在分叉期间都不会更改。程序有责任根据需要管理这些描述符。
- 瓦尔格林德错误来自 boost::asio
- 在网络套接字计时器滴答后增加asio短读错误
- 错误: C1083: 无法打开包含文件:"boost/asio.hpp": 没有此类文件或目录
- 使用 Boost ASIO 和 SSL 时出现"Wrong Version Number"错误 (C++)
- 尝试关闭 SSL 套接字时使用升压 asio 1.64 的分段错误 (SIGSEGV)
- 提升 asio 回声服务器示例中的黑客或错误?
- C++ Boost::asio x64 async_send失败,出现错误 10014 (WSAEFAULT)
- boost::asio async_accept总是发生错误,error_code.value() 是 22,这意味着参
- 编译Boost ASIO示例时出现错误
- 加速 ASIO 系统错误 995:I/O 操作已中止
- 尝试重新连接到服务器时获取错误提升 asio 连接超时
- 提升 ASIO 绑定:错误的文件描述符
- boost asio错误类别为空
- C++Boost.Asio错误在async_receive和async_send处理程序中
- c++Boost asio错误:没有共享密码
- 助推器::ASIO 错误?task_io_service在销毁io_service之前
- 提升 Asio 错误
- windows上的boost.asio错误代码依赖于平台
- 在iOS上提升ASIO错误"Host not found"
- 读/写超过100000条消息时出现boost asio错误