Соединения Poco HTTPServer все еще обслуживаются после вызова stop () и деструктора - PullRequest
4 голосов
/ 14 июня 2011

У меня проблема с использованием Poco :: HTTPServer.Как описано в документе TCPServer:

После вызова stop () новые соединения не будут приняты, и все соединения в очереди будут отброшены.Однако уже обслуживаемые соединения будут продолжаться.

Каждое соединение выполняется в своем собственном потоке.Хотя кажется, что деструктор успешно называется потоком соединений, он все еще существует и обслуживает соединения, что приводит к ошибкам сегментации.

Я хочу отменить все соединения.Поэтому я использую Poco::ThreadPool::defaultPool().stopAll(); в деструкторе моего серверного класса, что приводит к поведению, также описанному в документах ThreadPool (это занимает 10 секунд и объекты не удаляются):

Если поток не может остановиться в течение 10 секунд (например, из-за ошибки программирования), базовый объект потока не будет удален, и этот метод все равно вернется.Это позволяет более или менее плавно завершать работу в случае неправильного поведения потока.

Мой вопрос: как мне выполнить более изящный путь?Ошибка программирования в Poco-библиотеке?

РЕДАКТИРОВАТЬ: я использую GNU / Linux (Ubuntu 10.04) с eclipse + cdt в качестве IDE, целевой системой является встроенный Linux (Kernel 2.6.9).В обеих системах я испытал описанное поведение.

Приложение, над которым я работаю, должно быть настроено через веб-интерфейс.Таким образом, сервер отправляет событие (при загрузке новой конфигурации) на главный для перезапуска.

Вот схема:

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

Ответы [ 2 ]

6 голосов
/ 02 мая 2014

На самом деле это ошибка в реализации метода stopAll ().Прослушивающий сокет отключается после закрытия активных в данный момент соединений, что позволяет серверу принимать новые соединения между ними, которые, в свою очередь, не будут закрыты и продолжат работу.Обходной путь должен вызвать HTTPServer :: stop () и затем HTTPServer :: stopAll ().Я сообщил об ошибке в апстриме, включая предлагаемое исправление:

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

0 голосов
/ 04 июня 2013

Вам следует избегать использования 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
    }
};

Этот ответ может быть слишком поздно для автора, но так как вопрос помог мнеЧтобы решить мою проблему, я думаю, что это хорошо, чтобы опубликовать решение здесь!

...