4

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(); }
}
rubo77
  • 19,527
  • 31
  • 134
  • 226
Michael
  • 98
  • 1
  • 9
  • the poco tag: Means Plain Old CLR Object, a simple object that does not follow any object model, convention or framework. Somehow i don't think you meant that – Tim Jun 14 '11 at 09:55
  • 2
    Could someone with heaps of rep create a tag for the Poco C++ Libraries http://pocoproject.org/ – Tim Jun 14 '11 at 10:08

2 Answers2

6

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

kblaschke
  • 76
  • 1
  • 2
0

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 !

Matthieu Rouget
  • 3,289
  • 18
  • 23
  • Thanks for the answer, it's too late for the project but not for me, cheers – Michael Jun 17 '13 at 19:07
  • Now that I looked at the problem again, I saw that Poco::HTTPServer now has a method stopAll() which might cancel all current connections. I don't think it had that in 2011... – Michael Jun 17 '13 at 19:25
  • 1
    `Poco::HTTPServer::stopAll()` used alone does not solve the issue. My tests pass if I use `stop` then `stopAll`... but after reading the code, I saw the `stopAll` does nothing more than sending an event (inherently asynchronous) to the connection threads and then calling `stop`... Thus I am not very confident in using `stopAll`. Anyway, thanks for accepting my answer two years later ! – Matthieu Rouget Jun 18 '13 at 07:09