From cd380a84946078861e488c88cf7454f3cd905d38 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 28 Feb 2015 08:43:49 +0100 Subject: [PATCH] Fix another crash in Timer::Call fixes #8550 --- lib/base/streamlogger.cpp | 3 +++ lib/base/timer.cpp | 33 +++++++++++++++++---------------- lib/base/timer.hpp | 3 ++- lib/base/workqueue.cpp | 2 ++ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/base/streamlogger.cpp b/lib/base/streamlogger.cpp index ccb4eb351..024a9ef5a 100644 --- a/lib/base/streamlogger.cpp +++ b/lib/base/streamlogger.cpp @@ -59,6 +59,9 @@ void StreamLogger::Stop(void) */ StreamLogger::~StreamLogger(void) { + if (m_FlushLogTimer) + m_FlushLogTimer->Stop(); + if (m_OwnsStream) delete m_Stream; } diff --git a/lib/base/timer.cpp b/lib/base/timer.cpp index 4bd22de26..dd3d68b4c 100644 --- a/lib/base/timer.cpp +++ b/lib/base/timer.cpp @@ -58,10 +58,6 @@ Timer::Timer(void) Timer::~Timer(void) { Stop(); - - boost::mutex::scoped_lock lock(l_TimerMutex); - while (m_Running) - l_TimerCV.wait(lock); } /** @@ -99,19 +95,12 @@ void Timer::Call(void) try { OnTimerExpired(Timer::Ptr(this)); } catch (...) { - Reschedule(); + InternalReschedule(true); throw; } - { - boost::mutex::scoped_lock lock(l_TimerMutex); - m_Running = false; - l_TimerCV.notify_all(); - } - - Reschedule(); - + InternalReschedule(true); } /** @@ -152,13 +141,13 @@ void Timer::Start(void) m_Started = true; } - Reschedule(); + InternalReschedule(false); } /** * Unregisters the timer and stops processing events for it. */ -void Timer::Stop(void) +void Timer::Stop(bool wait) { ASSERT(!OwnsLock()); @@ -172,20 +161,32 @@ void Timer::Stop(void) /* Notify the worker thread that we've disabled a timer. */ l_TimerCV.notify_all(); + + while (wait && m_Running) + l_TimerCV.wait(lock); +} + +void Timer::Reschedule(double next) +{ + InternalReschedule(false, next); } /** * Reschedules this timer. * + * @param completed Whether the timer has just completed its callback. * @param next The time when this timer should be called again. Use -1 to let * the timer figure out a suitable time based on the interval. */ -void Timer::Reschedule(double next) +void Timer::InternalReschedule(bool completed, double next) { ASSERT(!OwnsLock()); boost::mutex::scoped_lock lock(l_TimerMutex); + if (completed) + m_Running = false; + if (next < 0) { /* Don't schedule the next call if this is not a periodic timer. */ if (m_Interval <= 0) diff --git a/lib/base/timer.hpp b/lib/base/timer.hpp index bb2afdc3d..6bc421452 100644 --- a/lib/base/timer.hpp +++ b/lib/base/timer.hpp @@ -45,7 +45,7 @@ public: static void AdjustTimers(double adjustment); void Start(void); - void Stop(void); + void Stop(bool wait = false); void Reschedule(double next = -1); double GetNext(void) const; @@ -84,6 +84,7 @@ private: bool m_Running; /**< Whether the timer proc is currently running. */ void Call(); + void InternalReschedule(bool completed, double next = -1); static void TimerThreadProc(void); diff --git a/lib/base/workqueue.cpp b/lib/base/workqueue.cpp index e8209fe98..a09928e57 100644 --- a/lib/base/workqueue.cpp +++ b/lib/base/workqueue.cpp @@ -44,6 +44,8 @@ WorkQueue::WorkQueue(size_t maxItems, int threadCount) WorkQueue::~WorkQueue(void) { + m_StatusTimer->Stop(); + Join(true); }