Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2017-06-28 13:13:07 +0300
committerYuri Gorshenin <y@maps.me>2017-06-28 13:13:07 +0300
commitde0701fa0964ccc8f499d288a7d35a65043eb034 (patch)
treec1a7698070389cae3c0f7fc9bf7908b221413852 /base
parentdcb52b40df53e97ceed3bd77847607f37f2f6d0c (diff)
[base] Fixed possible deadlock on WorkerThread shutdown.
Diffstat (limited to 'base')
-rw-r--r--base/base_tests/worker_thread_tests.cpp19
-rw-r--r--base/worker_thread.cpp5
2 files changed, 20 insertions, 4 deletions
diff --git a/base/base_tests/worker_thread_tests.cpp b/base/base_tests/worker_thread_tests.cpp
index be601e1540..309112bf00 100644
--- a/base/base_tests/worker_thread_tests.cpp
+++ b/base/base_tests/worker_thread_tests.cpp
@@ -3,6 +3,7 @@
#include "base/worker_thread.hpp"
#include <condition_variable>
+#include <future>
#include <mutex>
using namespace base;
@@ -67,4 +68,22 @@ UNIT_TEST(WorkerThread_SimpleFlush)
}
TEST_EQUAL(value, 1024, ());
}
+
+UNIT_TEST(WorkerThread_PushFromPendingTask)
+{
+ // promise - future pair is used as a socketpair here to pass a
+ // signal from the main thread to the worker thread.
+ promise<void> p;
+ auto f = p.get_future();
+
+ WorkerThread thread;
+ bool const rv = thread.Push([&]() {
+ f.get();
+ bool const rv = thread.Push([&]() { TEST(false, ("This task should not be executed")); });
+ TEST(!rv, ());
+ });
+ TEST(rv, ());
+ thread.Shutdown(WorkerThread::Exit::ExecPending);
+ p.set_value();
+}
} // namespace
diff --git a/base/worker_thread.cpp b/base/worker_thread.cpp
index f0dc9af050..dffbdc2ee2 100644
--- a/base/worker_thread.cpp
+++ b/base/worker_thread.cpp
@@ -20,14 +20,12 @@ void WorkerThread::ProcessTasks()
{
queue<Task> pending;
- unique_lock<mutex> lk(m_mu, defer_lock);
-
while (true)
{
Task task;
{
- lk.lock();
+ unique_lock<mutex> lk(m_mu);
m_cv.wait(lk, [this]() { return m_shutdown || !m_queue.empty(); });
if (m_shutdown)
@@ -46,7 +44,6 @@ void WorkerThread::ProcessTasks()
CHECK(!m_queue.empty(), ());
task = move(m_queue.front());
m_queue.pop();
- lk.unlock();
}
task();