1

I have wrote the simple code that demonstrate my problem with boost tcp server. The problem is that i can not stop and then again bind to the same port if application already has child processes, it (child) continue listening port even if parent process close acceptor.

#include <iostream>
#include <chrono>
#include <thread>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

using namespace std;

void handle_accept(boost::asio::ip::tcp::socket *sock, const boost::system::error_code & err)
 {
    if ( err) {
        cerr << "Err" << endl;
        return;
    }
}

int main() {

    boost::asio::io_service service;
    boost::asio::ip::tcp::endpoint ep( boost::asio::ip::address_v4::loopback(), 8080);
    boost::asio::ip::tcp::acceptor tcp_acceptor_(service);
    tcp_acceptor_.open(ep.protocol());
    tcp_acceptor_.bind(ep);
    tcp_acceptor_.listen();

    boost::asio::ip::tcp::socket socket(service);
    tcp_acceptor_.async_accept(socket, boost::bind( handle_accept, &socket, _1) );

    cout << "Acceptor started" << endl;

    system("sleep 600 &");
    std::this_thread::sleep_for(std::chrono::seconds(10));

    cout << "Close acceptor" << endl;

    tcp_acceptor_.close(); 

    std::this_thread::sleep_for(std::chrono::seconds(100));
    return 0;
}

When program started netstat shows that my program listening port 8080:

~/tmp/tcp_server$ netstat -tanp | grep 8080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      22340/a.out  

After call

tcp_acceptor_.close();

netstat shows that child program "sleep" continue listening port 8080

~/tmp/tcp_server$ netstat -tanp | grep 8080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      22342/sleep 

So as result I can not start listening port 8080 until "sleep" exited. I know that child process inherit open sockets, but how to properly start/stop/start listening port in program if it has child processes?

Yuri
  • 1,179
  • 4
  • 13
  • 27
  • Does this help - http://stackoverflow.com/questions/6014055/how-is-socket-connection-being-handled-in-a-forked-process? – Prabhu Oct 06 '16 at 18:31
  • Not, In a big application when fork child I don know which sockets are opened, from architecture point of view how to properly do this ? – Yuri Oct 06 '16 at 18:51
  • Problem fixed by adding fcntl(tcp_acceptor_.native(), F_SETFD, FD_CLOEXEC) – Yuri Oct 06 '16 at 19:24
  • If the `io_service` is not explicitly being informed about the fork, then it is invoking unspecified behavior. – Tanner Sansbury Oct 06 '16 at 19:28
  • @Tanner Sansbury, if i understood documentation correctly we have to notify io_service about fork() only if it forked inside handler invoked by this io_service only. But in the code above i forked (by system("sleep 600 &")) process outside io_service context. Please correct me if am wrong. – Yuri Oct 06 '16 at 19:38
  • I may be overlooking some of the documentation, but as far I know, this behavior does not change if the fork occurs from inside or outside of a completion handler. By the time `system()` is invoked, the `io_service`'s internal file descriptors have been created, and will be inherited by the child process. By being notified pre-fork and post-fork, the `io_service` will properly handle its internal descriptors. – Tanner Sansbury Oct 06 '16 at 19:59

0 Answers0