Overview
Features
Download
Documentation
Community
Add-Ons & Services

How do I cleanly terminate Poco::Net::TCPServer?

Please post support and help requests here.

How do I cleanly terminate Poco::Net::TCPServer?

Postby dbarzo » 05 Jun 2014, 12:21

Hi,

I posted the question on StackOverflow but I wanna replicate here to "keep track".

My server start a Poco::Task which, in turn, start a TCPServer (here I post "clean" code without other stuffs)

Code: Select all
int TBServer::main(const std::vector<std::string>& args) {
  TaskManager tm;
  tm.start(new ServerTask());
  waitForTerminationRequest();
  tm.cancelAll();
  tm.joinAll();
  return Application::EXIT_OK;
}


Code: Select all
class ServerTask : public Task {
public:

  ServerTask::ServerTask() : Task("TB Server") {
  }


  void ServerTask::runTask() {
    try {
      // Create the localhost tcp server to handle request from the php application
      local_svr.reset( new TCPServerWrap());
      local_svr->Start(5000);

      std::cout << "Application Started..." << std::endl;

        while(!isCancelled())
        {
        // Do nothing here...the logic is inside the TCPServer classes
           sleep(500);
        }

      std::cout << "Terminating Application..." << std::endl;

      local_svr->Stop();
    }
    catch (Poco::Exception e) {
      std::cout << e.what() << std::endl;
    }
  }

private:
  std::unique_ptr<TCPServerWrap> local_svr;
};


The TCPServerWrapper is:

Code: Select all
TCPServerWrap::TCPServerWrap() {
}
 
TCPServerWrap::~TCPServerWrap() {
}

Poco::Net::TCPServerConnection* TCPServerWrap::createConnection(const Poco::Net::StreamSocket& socket) {
  return new TCPConnection(socket);
}

int TCPServerWrap::Start(unsigned short port) {
 
  Poco::Net::ServerSocket svrSkt(port);
  m_tcp_srv_ptr.reset( new Poco::Net::TCPServer(this, svrSkt, new Poco::Net::TCPServerParams) );
  m_tcp_srv_ptr->start();
  return 0;
}

void TCPServerWrap::Stop() {
  if (m_tcp_srv_ptr)
    m_tcp_srv_ptr->stop();
}


The problem is that, when I close the application, I get a GPF error like something is destroyed twice or "too early", so my question is:

How can I "wait" for all threads to end before destroy objects?

If someone wanna test it, a simple project which reproduce the issue can be found here

Thanks in advance,
Daniele
dbarzo
 
Posts: 38
Joined: 14 Jan 2013, 17:15
Location: Italy

Re: How do I cleanly terminate Poco::Net::TCPServer?

Postby gregee123 » 06 Jun 2014, 15:40

You could check Poco::Net::TCPServer::currentThreads() and currentConnection() wait for them to return 0 BUT with the way you have it written your TCPConnection::run() will NEVER exit! Unless you can force an exception to be thrown by explicitly closing the socket (Poco::Net::TCPServer::socket()::close()) and then wait for currentConnectons() to return 0.

You seem to presume that the TCPConnection is destroyed as the TCPServer is stopped/destroyed. Well, that's not the case I'm afraid! The TCPConnection object (as well as Poco::Net::TCPDispatcher handling this connection) will exist in memory as your application exits ( the cause of GPF ?).

Problem is that the TCPServer doesn't notify its TCPConnections about being stopped. Poco::Net::HTTPServer has (what seems to be) a workaround for that problem with HTTPServerConnections listening to a serverStopped event from HTTPRequestHandlerFactory (doh!). Those working on TCP level are left to implement their own workaround, I guess.
currently using: 1.5.3
gregee123
 
Posts: 35
Joined: 29 Mar 2013, 12:11

Re: How do I cleanly terminate Poco::Net::TCPServer?

Postby dbarzo » 06 Jun 2014, 17:38

Hi gregee,

first of all....thanks a lot for your answer!

gregee123 wrote:You could check Poco::Net::TCPServer::currentThreads() and currentConnection() wait for them to return 0 BUT with the way you have it written your TCPConnection::run() will NEVER exit! Unless you can force an exception to be thrown by explicitly closing the socket (Poco::Net::TCPServer::socket()::close()) and then wait for currentConnectons() to return 0.

You seem to presume that the TCPConnection is destroyed as the TCPServer is stopped/destroyed. Well, that's not the case I'm afraid! The TCPConnection object (as well as Poco::Net::TCPDispatcher handling this connection) will exist in memory as your application exits ( the cause of GPF ?).


Yes, I had presumed that the TCPServer thread and the TCPConnections would have been destroyed by the destructor (or, at least, when I call close() ).
Moreover, the problem exists also if no connection is brought up!
If I start the server and I close it (without connect any client) I get the error.

gregee123 wrote:Problem is that the TCPServer doesn't notify its TCPConnections about being stopped. Poco::Net::HTTPServer has (what seems to be) a workaround for that problem with HTTPServerConnections listening to a serverStopped event from HTTPRequestHandlerFactory (doh!). Those working on TCP level are left to implement their own workaround, I guess.


Yes, I think the problem is the sync between various objects.
The other strange thing is that on linux it does not seems to give any errors (but I have to dig deeper).

Mmmm...I have to think a trick without touch the Poco code.
If you have some idea let me know! ;)

Cheers,
Daniele.
dbarzo
 
Posts: 38
Joined: 14 Jan 2013, 17:15
Location: Italy


Return to Support

Who is online

Users browsing this forum: No registered users and 1 guest

cron