Question

I am facing a problem using the Poco::HTTPServer. As descibed in the doc of TCPServer:

After calling stop(), no new connections will be accepted and all queued connections will be discarded. Already served connections, however, will continue being served.

Every connection is executed in its own thread. Although it seems the destructor is succesfully called the connection-thread still exists and serves connections, which leads to segmentation faults.

I want to cancel all connections. Therefore I use Poco::ThreadPool::defaultPool().stopAll(); in the destructor of my server class, which leads to the behaviour also described in the docs of ThreadPool (It takes 10 seconds and objects are not deleted):

If a thread fails to stop within 10 seconds (due to a programming error, for example), the underlying thread object will not be deleted and this method will return anyway. This allows for a more or less graceful shutdown in case of a misbehaving thread.

My question is: How do I accomplish the more graceful way? Is the programming error within the Poco-library?

EDIT: I am using GNU/Linux (Ubuntu 10.04) with eclipse + cdt as IDE, target system is embedded Linux (Kernel 2.6.9). On both systems I experienced the described behaviour.

The application I am working on shall be configured via web-interface. So the server sends an event (on upload of new configuration) to main to restart.

Here's the outline:

main{
    while (true){
        server = new Server(...);
        server->start();
        // wait for termination request
        server->stop();
        delete server;
    }
}

class Server{
    Poco:HTTPServer m_Server;

    Server(...):
         m_Server(requestHandlerFactory, socket, params);
    {
    }

    ~Server(){
         [...]
         Poco::ThreadPool::defaultPool().stopAll(); // This takes 10 seconds!
         // without the above line I get segmentation faults, 
         // because connections are still being served. 
    }

    start() { m_Server.start(); }
    stop() { m_Server.stop(); }
}
Was it helpful?

Solution

This is actually a bug in the implementation of the stopAll() method. The listening socket is being shut down after closing the currently active connections, which allows the server to accept new connections in between, which in turn will not be closed and keep running. A workaround is to call HTTPServer::stop() and then HTTPServer::stopAll(). I reported the bug upstream including a proposed fix:

https://github.com/pocoproject/poco/issues/436

OTHER TIPS

You should avoid using Poco::ThreadPool::defaultPool().stopAll(); since it doesn't provide you control on which threads are stopped.

I suggest you to create a Poco::ThreadPool specifically for you Poco:HTTPServer instance and stops the threads of this pool when your server is stopped.

With this, your code should look like this:

class Server{
    Poco:HTTPServer m_Server;
    Poco::ThreadPool m_threadPool;

    Server(...)
    : m_Server(requestHandlerFactory, m_threadPool, socket, params);
    {

    }

    ~Server(){

    }

    start() { m_Server.start(); }
    stop() { 
        m_Server.stop(); 
        m_threadPool.stopAll(); // Stop and wait serving threads
    }
};

This answer may be too late for the poster, but since the question helped me to solve my issue, I think it is good to post a solution here !

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top