]> granicus.if.org Git - icinga2/commitdiff
Fix another crash in Timer::Call
authorGunnar Beutner <gunnar@beutner.name>
Sat, 28 Feb 2015 07:43:49 +0000 (08:43 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Sat, 28 Feb 2015 07:43:49 +0000 (08:43 +0100)
fixes #8550

lib/base/streamlogger.cpp
lib/base/timer.cpp
lib/base/timer.hpp
lib/base/workqueue.cpp

index ccb4eb3515409eba57f873d7de071e4bc8e7e6dd..024a9ef5af48978f0ef1eacde594e3372c684d87 100644 (file)
@@ -59,6 +59,9 @@ void StreamLogger::Stop(void)
  */
 StreamLogger::~StreamLogger(void)
 {
+       if (m_FlushLogTimer)
+               m_FlushLogTimer->Stop();
+
        if (m_OwnsStream)
                delete m_Stream;
 }
index 4bd22de265fa9372664e166b86a88d7424f4a7b4..dd3d68b4c26fd1d06decb3e1fb27744091bd2d58 100644 (file)
@@ -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)
index bb2afdc3de0f5e0b2c60ae113dd7467f678e7b96..6bc42145239a735493247692d1a03d74bae97591 100644 (file)
@@ -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);
 
index e8209fe981ad03793d96f5435675254f818f9476..a09928e57d70abc52da6477c8dba0a89a85c2ad9 100644 (file)
@@ -44,6 +44,8 @@ WorkQueue::WorkQueue(size_t maxItems, int threadCount)
 
 WorkQueue::~WorkQueue(void)
 {
+       m_StatusTimer->Stop();
+
        Join(true);
 }