From 042e4270bf897df66778c8d54de72ec9d1a4836c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 9 May 2014 19:26:31 +0200 Subject: [PATCH] Fix an issue where expired Timer pointers caused other timers to be delayed. Fixes #6179 --- lib/base/timer.cpp | 50 ++++++++++++------------------- lib/base/timer.h | 2 -- lib/icinga/checkable-downtime.cpp | 2 ++ lib/icinga/checkable.cpp | 2 -- lib/icinga/service.cpp | 2 -- test/CMakeLists.txt | 4 +-- test/base-timer.cpp | 4 +-- 7 files changed, 25 insertions(+), 41 deletions(-) diff --git a/lib/base/timer.cpp b/lib/base/timer.cpp index 8afe259d7..323afc156 100644 --- a/lib/base/timer.cpp +++ b/lib/base/timer.cpp @@ -32,37 +32,17 @@ using namespace icinga; -/** - * @ingroup base - */ -struct icinga::TimerNextExtractor +struct TimerHolder { - typedef double result_type; - - /** - * Extracts the next timestamp from a Timer. - * - * Note: Caller must hold l_Mutex. - * - * @param wtimer Weak pointer to the timer. - * @returns The next timestamp - */ - double operator()(const weak_ptr& wtimer) const - { - Timer::Ptr timer = wtimer.lock(); - - if (!timer) - return 0; - - return timer->m_Next; - } + Timer::WeakPtr Object; + double Next; }; typedef boost::multi_index_container< - Timer::WeakPtr, + TimerHolder, boost::multi_index::indexed_by< - boost::multi_index::ordered_unique >, - boost::multi_index::ordered_non_unique + boost::multi_index::ordered_unique >, + boost::multi_index::ordered_non_unique > > > TimerSet; @@ -205,7 +185,11 @@ void Timer::Reschedule(double next) if (m_Started) { /* Remove and re-add the timer to update the index. */ l_Timers.erase(GetSelf()); - l_Timers.insert(GetSelf()); + + TimerHolder th; + th.Object = GetSelf(); + th.Next = m_Next; + l_Timers.insert(th); /* Notify the worker that we've rescheduled a timer. */ l_CV.notify_all(); @@ -242,8 +226,8 @@ void Timer::AdjustTimers(double adjustment) std::vector timers; - BOOST_FOREACH(const Timer::WeakPtr& wtimer, idx) { - Timer::Ptr timer = wtimer.lock(); + BOOST_FOREACH(const TimerHolder& th, idx) { + Timer::Ptr timer = th.Object.lock(); if (!timer) continue; @@ -257,7 +241,11 @@ void Timer::AdjustTimers(double adjustment) BOOST_FOREACH(const Timer::Ptr& timer, timers) { l_Timers.erase(timer); - l_Timers.insert(timer); + + TimerHolder th; + th.Object = timer; + th.Next = timer->m_Next; + l_Timers.insert(th); } /* Notify the worker that we've rescheduled some timers. */ @@ -285,7 +273,7 @@ void Timer::TimerThreadProc(void) break; NextTimerView::iterator it = idx.begin(); - Timer::Ptr timer = it->lock(); + Timer::Ptr timer = it->Object.lock(); if (!timer) { /* Remove the timer from the list if it's not alive anymore. */ diff --git a/lib/base/timer.h b/lib/base/timer.h index 9c0899047..cb0a81320 100644 --- a/lib/base/timer.h +++ b/lib/base/timer.h @@ -26,8 +26,6 @@ namespace icinga { -struct TimerNextExtractor; - /** * A timer that periodically triggers an event. * diff --git a/lib/icinga/checkable-downtime.cpp b/lib/icinga/checkable-downtime.cpp index 62fc77d47..bf0e6b4f8 100644 --- a/lib/icinga/checkable-downtime.cpp +++ b/lib/icinga/checkable-downtime.cpp @@ -39,6 +39,8 @@ boost::signals2::signal Checkable::OnDowntimeRemoved; boost::signals2::signal Checkable::OnDowntimeTriggered; +INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer); + int Checkable::GetNextDowntimeID(void) { boost::mutex::scoped_lock lock(l_DowntimeMutex); diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 9daf9c88f..cf589c492 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -37,8 +37,6 @@ using namespace icinga; REGISTER_TYPE(Checkable); -INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer); - boost::signals2::signal Checkable::OnAcknowledgementSet; boost::signals2::signal Checkable::OnAcknowledgementCleared; diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index 65e2d359d..bb311d70a 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -37,8 +37,6 @@ using namespace icinga; REGISTER_TYPE(Service); -INITIALIZE_ONCE(&Service::StartDowntimesExpiredTimer); - String ServiceNameComposer::MakeName(const String& shortName, const Dictionary::Ptr props) const { if (!props) return ""; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index eb947631f..cea166d0d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -68,8 +68,8 @@ add_boost_test(base base_string/find base_timer/construct base_timer/interval -# base_timer/invoke -# base_timer/scope + base_timer/invoke + base_timer/scope base_value/scalar base_value/convert base_value/format diff --git a/test/base-timer.cpp b/test/base-timer.cpp index 1a75b3fd9..1dfaa19f4 100644 --- a/test/base-timer.cpp +++ b/test/base-timer.cpp @@ -58,7 +58,7 @@ static void Callback(int *counter) (*counter)++; } -/*BOOST_AUTO_TEST_CASE(invoke) +BOOST_AUTO_TEST_CASE(invoke) { int counter; Timer::Ptr timer = make_shared(); @@ -87,6 +87,6 @@ BOOST_AUTO_TEST_CASE(scope) Utility::Sleep(5.5); BOOST_CHECK(counter >= 4 && counter <= 6); -}*/ +} BOOST_AUTO_TEST_SUITE_END()