From d7cf23ad6c2991c6dfe8dd0c66b311b1a721474c Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Sat, 17 Sep 2016 22:48:18 -0700 Subject: [PATCH] Fix incorrect WaitForStateUpdate behavior This routine must throw an exception if the thread is terminated during a wait. Ensure that `BasicThread::OnStop` signals the state mutex when it's called to cause any waiters to wake up. --- src/autowiring/BasicThread.cpp | 7 ++++++- src/autowiring/test/BasicThreadTest.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/autowiring/BasicThread.cpp b/src/autowiring/BasicThread.cpp index 80902bbb5..1c9357247 100644 --- a/src/autowiring/BasicThread.cpp +++ b/src/autowiring/BasicThread.cpp @@ -145,8 +145,13 @@ bool BasicThread::OnStart(void) { void BasicThread::OnStop(bool graceful) { // If we were never started, we need to set our completed flag to true - if (!m_wasStarted) + if (!m_wasStarted) { + std::lock_guard lk(m_state->m_lock); m_state->m_completed = true; + } + + // State condition must be notified, in the event that anything is blocking + m_state->m_stateCondition.notify_all(); // Always invoke stop handler: OnStop(); diff --git a/src/autowiring/test/BasicThreadTest.cpp b/src/autowiring/test/BasicThreadTest.cpp index 21335ce4e..f2aef6e92 100644 --- a/src/autowiring/test/BasicThreadTest.cpp +++ b/src/autowiring/test/BasicThreadTest.cpp @@ -75,3 +75,23 @@ TEST_F(BasicThreadTest, IsMainThread) { ); ASSERT_FALSE(secondaryIsMain.get()) << "Secondary thread incorrectly identified as the main thread"; } + +namespace { +class WaitsForStateUpdate : + public BasicThread +{ +public: + void Run(void) override { + WaitForStateUpdate([] { return false; }); + } +}; +} + +TEST_F(BasicThreadTest, WaitForStateUpdateExits) { + AutoRequired wfsu; + AutoCurrentContext ctxt; + ctxt->Initiate(); + + ctxt->SignalShutdown(); + ASSERT_TRUE(ctxt->Wait(std::chrono::seconds{ 10 })); +}