]> granicus.if.org Git - icinga2/commitdiff
Fix a crash in Timer::Call
authorGunnar Beutner <gunnar@beutner.name>
Fri, 27 Feb 2015 13:07:12 +0000 (14:07 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Fri, 27 Feb 2015 13:07:12 +0000 (14:07 +0100)
fixes #8473

lib/base/timer.cpp
lib/base/timer.hpp

index 8d9420850629adf66de3c620e2f0fe29d4041a95..632f4a226821056abab1de6bf62edccab029867f 100644 (file)
@@ -49,7 +49,7 @@ static TimerSet l_Timers;
  * Constructor for the Timer class.
  */
 Timer::Timer(void)
-       : m_Interval(0), m_Next(0)
+       : m_Interval(0), m_Next(0), m_Started(false), m_Running(false)
 { }
 
 /**
@@ -58,6 +58,10 @@ Timer::Timer(void)
 Timer::~Timer(void)
 {
        Stop();
+
+       boost::mutex::scoped_lock lock(l_TimerMutex);
+       while (m_Running)
+               l_TimerCV.wait(lock);
 }
 
 /**
@@ -100,7 +104,14 @@ void Timer::Call(void)
                throw;
        }
 
+       {
+               boost::mutex::scoped_lock lock(l_TimerMutex);
+               m_Running = false;
+               l_TimerCV.notify_all();
+       }
+
        Reschedule();
+
 }
 
 /**
@@ -172,6 +183,7 @@ void Timer::Stop(void)
 void Timer::Reschedule(double next)
 {
        ASSERT(!OwnsLock());
+       ASSERT(!m_Running);
 
        boost::mutex::scoped_lock lock(l_TimerMutex);
 
@@ -280,6 +292,8 @@ void Timer::TimerThreadProc(void)
                 * until the current call is completed. */
                l_Timers.erase(timer);
 
+               timer->m_Running = true;
+
                lock.unlock();
 
                /* Asynchronously call the timer. */
index 2150694532dfea77072ba7e12b44e63e0d772a99..bb2afdc3de0f5e0b2c60ae113dd7467f678e7b96 100644 (file)
@@ -81,6 +81,7 @@ private:
        double m_Interval; /**< The interval of the timer. */
        double m_Next; /**< When the next event should happen. */
        bool m_Started; /**< Whether the timer is enabled. */
+       bool m_Running; /**< Whether the timer proc is currently running. */
 
        void Call();