all repos — fluxbox @ 4d307dcd10af9d817ff5c05fc40ae7487564cb31

custom fork of the fluxbox windowmanager

Fix bug: handle the list of Timers not in-place

With commit 541c8c4 we switched from an (manually) ordered list to a
std::set<> to handle the active timers. The code which checks for overdue
timers now traverses and modifies the std::set<> in place. This might
lead to an infinite loop. Examples of such bad behavior are "flickering of
the tooltip" (bug #3590078) or crashes (bug #3600143) or just insanely high
cpu load when autoraising windows or submenus.

We now make a copy of the std::set<> traverse this instead of the original.
Mathias Gumz akira at fluxbox dot org
commit

4d307dcd10af9d817ff5c05fc40ae7487564cb31

parent

06655f6d7ff2af0626d37f083b927af2af1be529

1 files changed, 18 insertions(+), 14 deletions(-)

jump to
M src/FbTk/Timer.ccsrc/FbTk/Timer.cc

@@ -52,6 +52,7 @@ # include <winsock.h>

#endif #include <cstdio> +#include <vector> #include <set>

@@ -195,32 +196,35 @@ // didn't time out! x events are pending

return; } + // stoping / restarting the timers modifies the list in an upredictable + // way. to avoid problems such as infinite loops we save the current + // (ordered) list of timers into a list and work on it. + + ssize_t i; + const ssize_t ts = s_timerlist.size(); + std::vector<FbTk::Timer*> timers; + + timers.reserve(ts); + for (it = s_timerlist.begin(); it != s_timerlist.end(); ++it ) { + timers.push_back(*it); + } + now = FbTime::now(); - for (it = s_timerlist.begin(); it != s_timerlist.end(); ) { + for (i = 0; i < ts; ++i) { + + FbTk::Timer* t = timers[i]; - // t->fireTimeout() might add timers to the list - // this invalidates 'it'. thus we store the current timer - Timer* t = *it; if (now < t->getEndTime()) { break; } t->fireTimeout(); - - // find the iterator to the timer again - // and continue working on the list - it = s_timerlist.find(t); - it++; - s_timerlist.erase(t); + t->stop(); if (! t->doOnce()) { // restart the current timer - t->m_timing = false; t->start(); - } else { - t->stop(); } } - }