From: Gunnar Beutner Date: Thu, 13 Nov 2014 09:00:49 +0000 (+0100) Subject: Fix deadlock in ThreadPool::Stop X-Git-Tag: v2.2.0~39 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f20d9010c07ce108636cf3a582bf9b19d080a46c;p=icinga2 Fix deadlock in ThreadPool::Stop --- diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 204ca752d..d5085bfd7 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -321,8 +321,6 @@ mainloop: GetTP().Stop(); m_ShuttingDown = false; - GetTP().Join(true); - Timer::Uninitialize(); #endif /* _DEBUG */ } diff --git a/lib/base/threadpool.cpp b/lib/base/threadpool.cpp index d35bf69f4..3ffae3a93 100644 --- a/lib/base/threadpool.cpp +++ b/lib/base/threadpool.cpp @@ -41,7 +41,6 @@ ThreadPool::ThreadPool(size_t max_threads) ThreadPool::~ThreadPool(void) { Stop(); - Join(true); } void ThreadPool::Start(void) @@ -49,38 +48,26 @@ void ThreadPool::Start(void) for (size_t i = 0; i < sizeof(m_Queues) / sizeof(m_Queues[0]); i++) m_Queues[i].SpawnWorker(m_ThreadGroup); - m_ThreadGroup.create_thread(boost::bind(&ThreadPool::ManagerThreadProc, this)); + m_MgmtThread = boost::move(boost::thread(boost::bind(&ThreadPool::ManagerThreadProc, this))); } void ThreadPool::Stop(void) { - for (size_t i = 0; i < sizeof(m_Queues) / sizeof(m_Queues[0]); i++) { - boost::mutex::scoped_lock lock(m_Queues[i].Mutex); - m_Queues[i].Stopped = true; - m_Queues[i].CV.notify_all(); + { + boost::mutex::scoped_lock lock(m_MgmtMutex); + m_Stopped = true; + m_MgmtCV.notify_all(); } - boost::mutex::scoped_lock lock(m_MgmtMutex); - m_Stopped = true; - m_MgmtCV.notify_all(); -} - -/** - * Waits for all worker threads to finish. - */ -void ThreadPool::Join(bool wait_for_stop) -{ - if (wait_for_stop) { - m_ThreadGroup.join_all(); - return; - } + m_MgmtThread.join(); for (size_t i = 0; i < sizeof(m_Queues) / sizeof(m_Queues[0]); i++) { boost::mutex::scoped_lock lock(m_Queues[i].Mutex); - - while (!m_Queues[i].Items.empty()) - m_Queues[i].CVStarved.wait(lock); + m_Queues[i].Stopped = true; + m_Queues[i].CV.notify_all(); } + + m_ThreadGroup.join_all(); } /** diff --git a/lib/base/threadpool.hpp b/lib/base/threadpool.hpp index c34fd80a8..afae6c0b8 100644 --- a/lib/base/threadpool.hpp +++ b/lib/base/threadpool.hpp @@ -53,7 +53,6 @@ public: void Start(void); void Stop(void); - void Join(bool wait_for_stop = false); bool Post(const WorkFunction& callback, SchedulerPolicy policy = DefaultScheduler); @@ -122,6 +121,7 @@ private: boost::thread_group m_ThreadGroup; + boost::thread m_MgmtThread; boost::mutex m_MgmtMutex; boost::condition_variable m_MgmtCV; bool m_Stopped;