4

我在使用 Poco::HTTPServer 时遇到问题。如 TCPServer 的文档中所述:

调用 stop() 后,不会接受新的连接,所有排队的连接都将被丢弃。然而,已经服务的连接将继续被服务。

每个连接都在自己的线程中执行。尽管析构函数似乎被成功调用,但连接线程仍然存在并为连接提供服务,这会导致分段错误。

我想取消所有连接。因此,我Poco::ThreadPool::defaultPool().stopAll();在我的服务器类的析构函数中使用,这导致了 ThreadPool 文档中也描述的行为(它需要10 秒并且对象不会被删除):

如果一个线程未能在 10 秒内停止(例如由于编程错误),则不会删除底层线程对象,并且该方法无论如何都会返回。这允许在线程行为不端的情况下或多或少地优雅地关闭。

我的问题是:我如何完成更优雅的方式?Poco 库中是否存在编程错误?

编辑:我使用 GNU/Linux(Ubuntu 10.04)和 eclipse + cdt 作为 IDE,目标系统是嵌入式 Linux(内核 2.6.9)。在这两个系统上,我都经历了所描述的行为。

我正在处理的应用程序应通过 Web 界面进行配置。因此,服务器向 main 发送一个事件(在上传新配置时)以重新启动。

这是大纲:

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(); }
}
4

2 回答 2

6

这实际上是 stopAll() 方法实现中的一个错误。关闭当前活动的连接后正在关闭侦听套接字,这允许服务器在其间接受新连接,而这些连接又不会关闭并继续运行。一种解决方法是调用 HTTPServer::stop(),然后调用 HTTPServer::stopAll()。我报告了上游的错误,包括建议的修复:

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

于 2014-05-02T12:21:12.550 回答
0

您应该避免使用Poco::ThreadPool::defaultPool().stopAll();,因为它不能让您控制停止哪些线程。

Poco::ThreadPool我建议您专门为您创建一个Poco:HTTPServer实例,并在您的服务器停止时停止该池的线程。

有了这个,你的代码应该是这样的:

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
    }
};

这个答案对于发帖者来说可能为时已晚,但由于这个问题帮助我解决了我的问题,我认为在这里发布解决方案很好!

于 2013-06-04T13:30:15.267 回答