diff options
| author | Vaxry <vaxry@vaxry.net> | 2025-07-19 16:47:14 +0200 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2025-07-19 16:47:14 +0200 |
| commit | 8b383530122b972ca69cdac33427facf7b8aaadf (patch) | |
| tree | 177c7920cedd987f758fcc0d73b086a35aca7f8c /src/managers/eventLoop/EventLoopManager.cpp | |
| parent | 3b04131259bad140183a3825b981ebe30b61e524 (diff) | |
eventloop: improve timer handling to avoid crashes
ref #11062
Diffstat (limited to 'src/managers/eventLoop/EventLoopManager.cpp')
| -rw-r--r-- | src/managers/eventLoop/EventLoopManager.cpp | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 0389e7b8..b9ac7242 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -102,25 +102,25 @@ void CEventLoopManager::enterLoop() { void CEventLoopManager::onTimerFire() { const auto CPY = m_timers.timers; for (auto const& t : CPY) { - if (t.strongRef() > 1 /* if it's 1, it was lost. Don't call it. */ && t->passed() && !t->cancelled()) + if (t.strongRef() > 2 /* if it's 2, it was lost. Don't call it. */ && t->passed() && !t->cancelled()) t->call(t); } - nudgeTimers(); + scheduleRecalc(); } void CEventLoopManager::addTimer(SP<CEventLoopTimer> timer) { if (std::ranges::contains(m_timers.timers, timer)) return; m_timers.timers.emplace_back(timer); - nudgeTimers(); + scheduleRecalc(); } void CEventLoopManager::removeTimer(SP<CEventLoopTimer> timer) { if (!std::ranges::contains(m_timers.timers, timer)) return; std::erase_if(m_timers.timers, [timer](const auto& t) { return timer == t; }); - nudgeTimers(); + scheduleRecalc(); } static void timespecAddNs(timespec* pTimespec, int64_t delta) { @@ -136,7 +136,21 @@ static void timespecAddNs(timespec* pTimespec, int64_t delta) { } } +void CEventLoopManager::scheduleRecalc() { + // do not do it instantly, do it later. Avoid recursive access to the timer + // vector, it could be catastrophic if we modify it while iterating + + if (m_timers.recalcScheduled) + return; + + m_timers.recalcScheduled = true; + + doLater([this] { nudgeTimers(); }); +} + void CEventLoopManager::nudgeTimers() { + m_timers.recalcScheduled = false; + // remove timers that have gone missing std::erase_if(m_timers.timers, [](const auto& t) { return t.strongRef() <= 1; }); |
