mirror of https://github.com/Icinga/icinga2.git
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 <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
|
@ -61,6 +62,15 @@ static int l_AliveTimers = 0;
|
|||
|
||||
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.
|
||||
*/
|
||||
|
@ -316,11 +326,18 @@ void Timer::TimerThreadProc()
|
|||
* until the current call is completed. */
|
||||
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;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
/* 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:
|
||||
typedef std::shared_ptr<Timer> Ptr;
|
||||
|
||||
static inline
|
||||
Ptr Create()
|
||||
{
|
||||
return Ptr(new Timer());
|
||||
}
|
||||
static Ptr Create();
|
||||
|
||||
~Timer();
|
||||
|
||||
|
@ -52,6 +48,7 @@ private:
|
|||
double m_Next{0}; /**< When the next event should happen. */
|
||||
bool m_Started{false}; /**< Whether the timer is enabled. */
|
||||
bool m_Running{false}; /**< Whether the timer proc is currently running. */
|
||||
std::weak_ptr<Timer> m_Self;
|
||||
|
||||
Timer() = default;
|
||||
void Call();
|
||||
|
|
Loading…
Reference in New Issue