From 593850b956ddb7b7918e303898f95fa7a8f04174 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 10 Aug 2015 11:58:33 +0200 Subject: [PATCH] Fix potential race in dispatcher wakeup --- src/hydra-queue-runner/dispatcher.cc | 18 ++++++++++++------ src/hydra-queue-runner/state.hh | 4 ++-- src/hydra-queue-runner/sync.hh | 8 ++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/hydra-queue-runner/dispatcher.cc b/src/hydra-queue-runner/dispatcher.cc index 6bfeedae..3f3776c4 100644 --- a/src/hydra-queue-runner/dispatcher.cc +++ b/src/hydra-queue-runner/dispatcher.cc @@ -36,11 +36,14 @@ void State::dispatcher() /* Sleep until we're woken up (either because a runnable build is added, or because a build finishes). */ { - std::unique_lock lock(dispatcherMutex); - printMsg(lvlDebug, format("dispatcher sleeping for %1%s") % - std::chrono::duration_cast(sleepUntil - std::chrono::system_clock::now()).count()); - dispatcherWakeup.wait_until(lock, sleepUntil); + auto dispatcherWakeup_(dispatcherWakeup.lock()); + if (!*dispatcherWakeup_) { + printMsg(lvlDebug, format("dispatcher sleeping for %1%s") % + std::chrono::duration_cast(sleepUntil - std::chrono::system_clock::now()).count()); + dispatcherWakeup_.wait_until(dispatcherWakeupCV, sleepUntil); + } nrDispatcherWakeups++; + *dispatcherWakeup_ = false; } } @@ -167,6 +170,9 @@ system_time State::doDispatch() void State::wakeDispatcher() { - { std::lock_guard lock(dispatcherMutex); } // barrier - dispatcherWakeup.notify_one(); + { + auto dispatcherWakeup_(dispatcherWakeup.lock()); + *dispatcherWakeup_ = true; + } + dispatcherWakeupCV.notify_one(); } diff --git a/src/hydra-queue-runner/state.hh b/src/hydra-queue-runner/state.hh index 90306161..f5043975 100644 --- a/src/hydra-queue-runner/state.hh +++ b/src/hydra-queue-runner/state.hh @@ -202,8 +202,8 @@ private: Sync runnable; /* CV for waking up the dispatcher. */ - std::condition_variable dispatcherWakeup; - std::mutex dispatcherMutex; + Sync dispatcherWakeup; + std::condition_variable_any dispatcherWakeupCV; /* PostgreSQL connection pool. */ Pool dbPool; diff --git a/src/hydra-queue-runner/sync.hh b/src/hydra-queue-runner/sync.hh index aadaa838..1573f091 100644 --- a/src/hydra-queue-runner/sync.hh +++ b/src/hydra-queue-runner/sync.hh @@ -60,6 +60,14 @@ public: assert(s); return cv.wait_for(s->mutex, duration, pred); } + + template + std::cv_status wait_until(std::condition_variable_any & cv, + const std::chrono::time_point & duration) + { + assert(s); + return cv.wait_until(s->mutex, duration); + } }; Lock lock() { return Lock(this); }