I have a program that listens on a TCP port for a specific line and launches the application by calling execlp . I am doing fork() to start the child process before this execlp call. After that, the parent start process will again start listening on the same port. I close the socket in the child process.
I wrote a wrapper on top of boost::asio::tcp_socket , where before setting the socket I set the addr_reuse parameter to true .
Now my problem is Linux. I get an address reuse error after several application launches. In my program, he constantly tries to accept connections (or, rather, tries to schedule a reception until boost::asio::io_service ) until it is bound and then accepts successful execution. Therefore, I get an error in this loop.
Oddly enough, if I close (or kill) the running executable, this error will stop appearing, which means bind . I am sure that in the running application the same port is not used anywhere. I use asynchronous socket operations. Any idea why I am getting this error?
Here's how I accept on a socket: (I also call reset in boost::asio::tcp_socket(_tcpSocket) generic pointer before starting a new accept.)
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) );
This is how I deploy:
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: }
I removed logging for simplicity.