mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-16 18:24:31 +02:00
Timer::TimerThreadProc(): keep a Timer alive while it's running
to prevent the case: Timer callback destroys parent object -> destroys Timer -> ~Timer() -> Stop(true) -> waits for the Timer callback to finish -> deadlock.
This commit is contained in:
parent
9b00c1c4dd
commit
1badbab002
@ -12,6 +12,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
@ -61,6 +62,15 @@ static int l_AliveTimers = 0;
|
|||||||
|
|
||||||
static Defer l_ShutdownTimersCleanlyOnExit (&Timer::Uninitialize);
|
static Defer l_ShutdownTimersCleanlyOnExit (&Timer::Uninitialize);
|
||||||
|
|
||||||
|
Timer::Ptr Timer::Create()
|
||||||
|
{
|
||||||
|
Ptr t (new Timer());
|
||||||
|
|
||||||
|
t->m_Self = t;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor for the Timer class.
|
* Destructor for the Timer class.
|
||||||
*/
|
*/
|
||||||
@ -316,11 +326,18 @@ void Timer::TimerThreadProc()
|
|||||||
* until the current call is completed. */
|
* until the current call is completed. */
|
||||||
l_Timers.erase(timer);
|
l_Timers.erase(timer);
|
||||||
|
|
||||||
|
auto keepAlive (timer->m_Self.lock());
|
||||||
|
|
||||||
|
if (!keepAlive) {
|
||||||
|
// The last std::shared_ptr is gone, let ~Timer() proceed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
timer->m_Running = true;
|
timer->m_Running = true;
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
/* Asynchronously call the timer. */
|
/* Asynchronously call the timer. */
|
||||||
Utility::QueueAsyncCallback([timer]() { timer->Call(); });
|
Utility::QueueAsyncCallback([timer=std::move(keepAlive)]() { timer->Call(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,7 @@ class Timer final
|
|||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<Timer> Ptr;
|
typedef std::shared_ptr<Timer> Ptr;
|
||||||
|
|
||||||
static inline
|
static Ptr Create();
|
||||||
Ptr Create()
|
|
||||||
{
|
|
||||||
return Ptr(new Timer());
|
|
||||||
}
|
|
||||||
|
|
||||||
~Timer();
|
~Timer();
|
||||||
|
|
||||||
@ -52,6 +48,7 @@ private:
|
|||||||
double m_Next{0}; /**< When the next event should happen. */
|
double m_Next{0}; /**< When the next event should happen. */
|
||||||
bool m_Started{false}; /**< Whether the timer is enabled. */
|
bool m_Started{false}; /**< Whether the timer is enabled. */
|
||||||
bool m_Running{false}; /**< Whether the timer proc is currently running. */
|
bool m_Running{false}; /**< Whether the timer proc is currently running. */
|
||||||
|
std::weak_ptr<Timer> m_Self;
|
||||||
|
|
||||||
Timer() = default;
|
Timer() = default;
|
||||||
void Call();
|
void Call();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user