From 58c030adc868fb182246e892afbb08f576c02438 Mon Sep 17 00:00:00 2001 From: Jan Oravec Date: Sat, 1 Jun 2013 20:00:37 -0700 Subject: [PATCH] Fix race condition in ExternalThreadEvents A race condition can occur when the processing thread tries to notify condition that is not yet waited upon. This can happen during the short window in the web request thread between transitioning to the WAITING state and calling condition.wait(). Fix this by locking mutex right before notifying the condition. If the web request thread is in WAITING state, it is guaranteed to hold the mutex or wait for condition variable. If the processing thread was able to transition away from the WAITING state and grabbed the lock, the web request thread must be waiting on condition variable, so it is safe to notify it. Thanks @andrii for tracking the bug down to ExternalThreadEvents and providing a workaround (grabbing the mutex few lines up than this diff). --- hphp/runtime/ext/asio/asio_session.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hphp/runtime/ext/asio/asio_session.cpp b/hphp/runtime/ext/asio/asio_session.cpp index 115ba6c6f..0fb9d6620 100644 --- a/hphp/runtime/ext/asio/asio_session.cpp +++ b/hphp/runtime/ext/asio/asio_session.cpp @@ -111,6 +111,7 @@ void AsioSession::enqueueExternalThreadEvent(c_ExternalThreadEventWaitHandle* wa wait_handle->setNextToProcess(nullptr); if (m_readyExternalThreadEvents.compare_exchange_weak(next, wait_handle)) { // succeeded, notify condition + std::unique_lock lock(m_readyExternalThreadEventsMutex); m_readyExternalThreadEventsCondition.notify_one(); return; }