From fdbfda848fc8265fadb9deca5e40ae8c9748d9c1 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Tue, 4 Jul 2017 23:06:59 +0100 Subject: [PATCH] T102 Don't try to wait for a worker to finish while holding a lock on the mutex that protects its finished flag, as it will deadlock. --- src/blackcore/db/backgrounddataupdater.cpp | 8 +++++++- src/blackmisc/worker.h | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/blackcore/db/backgrounddataupdater.cpp b/src/blackcore/db/backgrounddataupdater.cpp index bd97427cc..9a5b45ff0 100644 --- a/src/blackcore/db/backgrounddataupdater.cpp +++ b/src/blackcore/db/backgrounddataupdater.cpp @@ -75,7 +75,13 @@ namespace BlackCore m_enabled = false; if (!CThreadUtils::isCurrentThreadObjectThread(this)) { - doIfNotFinished([this] { this->abandonAndWait(); }); + std::promise promise; + doIfFinishedElse([&promise] { promise.set_value(); }, [&promise, this] + { + this->then([&promise] { promise.set_value(); }); + this->abandon(); + }); + promise.get_future().wait(); } } diff --git a/src/blackmisc/worker.h b/src/blackmisc/worker.h index adf1d7e6d..2bde3c043 100644 --- a/src/blackmisc/worker.h +++ b/src/blackmisc/worker.h @@ -134,7 +134,7 @@ namespace BlackMisc } //! Executes some code (in the caller's thread) if the task has not finished. - //! \threadsafe + //! \threadsafe But the functor will deadlock if it waits for the task to finish. template void doIfNotFinished(F functor) const { @@ -142,8 +142,8 @@ namespace BlackMisc if (! m_finished) { functor(); } } - //! Executes some code (in the caller's thread) if the task has not finished and some different code if it has finished. - //! \threadsafe + //! Executes some code (in the caller's thread) if the task has finished and some different code if it has not finished. + //! \threadsafe But the elseFunctor will deadlock if it waits for the task to finish. template void doIfFinishedElse(F1 ifFunctor, F2 elseFunctor) const {