From 922277764d41e96a1c41291272bb70e3a1b8c677 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 3 May 2024 09:27:16 -0400 Subject: Prevent LLLater from thrashing on LLCallbackList. If there is exactly one doPeriodically() entry on LLLater, the mQueue entry is deleted before Periodic::operator()() is called. If Periodic's callable returns false, it reinstates itself on mQueue for a future time. That's okay, because the test for mQueue.empty(), and the consequent disconnect from LLCallbackList, happens only after that Periodic call returns. But at the moment Periodic reinstates itself on mQueue, mQueue happens to be empty. That alerts doAtTime2() to register itself on LLCallbackList -- even though at that moment it's already registered. Semantically that's okay because assigning to the LLLater's LLCallbackList::temp_handle_t should implicitly disconnect the previous connection. But it's pointless to create a new connection and disconnect the old one every time we call that lone Periodic. Add a test for mLive.connected(); that way if we already have an LLCallbackList connection, we retain it instead of replacing it with a new one. --- indra/llcommon/llcallbacklist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp index 19b948a5e1..992c83b4d2 100644 --- a/indra/llcommon/llcallbacklist.cpp +++ b/indra/llcommon/llcallbacklist.cpp @@ -152,7 +152,7 @@ LLLater::handle_t LLLater::doAtTime2(nullary_func_t callable, HandleMap::iterato auto handle{ mQueue.emplace(callable, iter->first, iter->second.second) }; // Now that we have an mQueue handle_type, store it in mHandles entry. iter->second.first = handle; - if (first) + if (first && ! mLive.connected()) { // If this is our first entry, register for regular callbacks. mLive = LLCallbackList::instance().doOnIdleRepeating([this]{ return tick(); }); -- cgit v1.2.3