]> granicus.if.org Git - icinga2/commitdiff
IoEngine: explicitly join I/O threads
authorAlexander A. Klimov <alexander.klimov@icinga.com>
Fri, 15 Feb 2019 14:43:58 +0000 (15:43 +0100)
committerAlexander A. Klimov <alexander.klimov@icinga.com>
Mon, 1 Apr 2019 09:40:14 +0000 (11:40 +0200)
lib/base/io-engine.cpp
lib/base/io-engine.hpp

index daad42df0e41edde7b3616ef950ff05fc8d6f6da..0079ca251d0121cfa9661c49c225074e4141cd19 100644 (file)
@@ -99,7 +99,7 @@ boost::asio::io_service& IoEngine::GetIoService()
        return m_IoService;
 }
 
-IoEngine::IoEngine() : m_IoService(), m_KeepAlive(m_IoService), m_AlreadyExpiredTimer(m_IoService)
+IoEngine::IoEngine() : m_IoService(), m_KeepAlive(m_IoService), m_Threads(decltype(m_Threads)::size_type(std::thread::hardware_concurrency())), m_AlreadyExpiredTimer(m_IoService)
 {
        m_AlreadyExpiredTimer.expires_at(boost::posix_time::neg_infin);
 
@@ -111,8 +111,21 @@ IoEngine::IoEngine() : m_IoService(), m_KeepAlive(m_IoService), m_AlreadyExpired
                m_CpuBoundSemaphore.store(concurrency - 1u);
        }
 
-       for (auto i (std::thread::hardware_concurrency()); i; --i) {
-               std::thread(&IoEngine::RunEventLoop, this).detach();
+       for (auto& thread : m_Threads) {
+               thread = std::thread(&IoEngine::RunEventLoop, this);
+       }
+}
+
+IoEngine::~IoEngine()
+{
+       for (auto& thread : m_Threads) {
+               m_IoService.post([]() {
+                       throw TerminateIoThread();
+               });
+       }
+
+       for (auto& thread : m_Threads) {
+               thread.join();
        }
 }
 
@@ -122,6 +135,8 @@ void IoEngine::RunEventLoop()
                try {
                        m_IoService.run();
 
+                       break;
+               } catch (const TerminateIoThread&) {
                        break;
                } catch (const std::exception& e) {
                        Log(LogCritical, "IoEngine", "Exception during I/O operation!");
index e383b2e421cebfbbee8752f6a4c5ac1322fcbc40..05610ca6f8850837e2ea54b6a89f4567a270924e 100644 (file)
 
 #include "base/lazy-init.hpp"
 #include <atomic>
+#include <exception>
 #include <memory>
+#include <thread>
+#include <vector>
 #include <boost/asio/deadline_timer.hpp>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/spawn.hpp>
@@ -82,6 +85,7 @@ public:
        IoEngine(IoEngine&&) = delete;
        IoEngine& operator=(const IoEngine&) = delete;
        IoEngine& operator=(IoEngine&&) = delete;
+       ~IoEngine();
 
        static IoEngine& Get();
 
@@ -96,8 +100,13 @@ private:
 
        boost::asio::io_service m_IoService;
        boost::asio::io_service::work m_KeepAlive;
+       std::vector<std::thread> m_Threads;
        boost::asio::deadline_timer m_AlreadyExpiredTimer;
        std::atomic_uint_fast32_t m_CpuBoundSemaphore;
 };
 
+class TerminateIoThread : public std::exception
+{
+};
+
 #endif /* IO_ENGINE_H */