From 9d82c1d8a9a350341ba2f0a00bbc3f3f201c5ae9 Mon Sep 17 00:00:00 2001 From: zhouzhenghui Date: Wed, 22 Dec 2021 02:47:13 +0800 Subject: [PATCH] fix deadlock in scoped_timer destructor (#5371) --- src/util/scoped_timer.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/util/scoped_timer.cpp b/src/util/scoped_timer.cpp index e144cf636e4..a36e762aa34 100644 --- a/src/util/scoped_timer.cpp +++ b/src/util/scoped_timer.cpp @@ -33,12 +33,14 @@ Revision History: #include #endif +enum scoped_timer_work_state { IDLE = 0, WORKING = 1, EXITING = 2 }; + struct scoped_timer_state { std::thread m_thread; std::timed_mutex m_mutex; event_handler * eh; unsigned ms; - std::atomic work; + std::atomic work; std::condition_variable_any cv; }; @@ -49,11 +51,11 @@ static atomic num_workers(0); static void thread_func(scoped_timer_state *s) { workers.lock(); while (true) { - s->cv.wait(workers, [=]{ return s->work > 0; }); + s->cv.wait(workers, [=]{ return s->work > IDLE; }); workers.unlock(); // exiting.. - if (s->work == 2) + if (s->work == EXITING) return; auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(s->ms); @@ -68,9 +70,8 @@ static void thread_func(scoped_timer_state *s) { s->m_mutex.unlock(); next: - s->work = 0; + s->work = IDLE; workers.lock(); - available_workers.push_back(s); } } @@ -97,7 +98,7 @@ struct scoped_timer::imp { s->ms = ms; s->eh = eh; s->m_mutex.lock(); - s->work = 1; + s->work = WORKING; if (new_worker) { s->m_thread = std::thread(thread_func, s); } @@ -108,8 +109,11 @@ struct scoped_timer::imp { ~imp() { s->m_mutex.unlock(); - while (s->work == 1) + while (s->work == WORKING) std::this_thread::yield(); + workers.lock(); + available_workers.push_back(s); + workers.unlock(); } }; @@ -139,7 +143,7 @@ void scoped_timer::finalize() { while (deleted < num_workers) { workers.lock(); for (auto w : available_workers) { - w->work = 2; + w->work = EXITING; w->cv.notify_one(); } decltype(available_workers) cleanup_workers;