mirror of
https://github.com/zeromq/libzmq.git
synced 2025-01-19 08:46:44 +01:00
Merge pull request #3925 from bjovke/timers_issue
Problem: Usage of invalidated iterator of _timers container in zmq::p…
This commit is contained in:
commit
6e62fb19b4
@ -68,8 +68,14 @@ void zmq::poller_base_t::cancel_timer (i_poll_events *sink_, int id_)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer not found.
|
// We should generally never get here. Calling 'cancel_timer ()' on
|
||||||
zmq_assert (false);
|
// an already expired or canceled timer (or even worse - on a timer which
|
||||||
|
// never existed, supplying bad sink_ and/or id_ values) does not make any
|
||||||
|
// sense.
|
||||||
|
// But in some edge cases this might happen. As described in issue #3645
|
||||||
|
// `timer_event ()` call from `execute_timers ()` might call `cancel_timer ()`
|
||||||
|
// on already canceled (deleted) timer.
|
||||||
|
// As soon as that is resolved an 'assert (false)' should be put here.
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t zmq::poller_base_t::execute_timers ()
|
uint64_t zmq::poller_base_t::execute_timers ()
|
||||||
@ -81,26 +87,31 @@ uint64_t zmq::poller_base_t::execute_timers ()
|
|||||||
// Get the current time.
|
// Get the current time.
|
||||||
const uint64_t current = _clock.now_ms ();
|
const uint64_t current = _clock.now_ms ();
|
||||||
|
|
||||||
// Execute the timers that are already due.
|
// Execute the timers that are already due.
|
||||||
const timers_t::iterator begin = _timers.begin ();
|
|
||||||
const timers_t::iterator end = _timers.end ();
|
|
||||||
uint64_t res = 0;
|
uint64_t res = 0;
|
||||||
timers_t::iterator it = begin;
|
timer_info_t timer_temp;
|
||||||
for (; it != end; ++it) {
|
timers_t::iterator it;
|
||||||
// If we have to wait to execute the item, same will be true about
|
|
||||||
// all the following items (multimap is sorted). Thus we can stop
|
do {
|
||||||
// checking the subsequent timers.
|
it = _timers.begin ();
|
||||||
|
|
||||||
|
// If we have to wait to execute the item, same will be true for
|
||||||
|
// all the following items because multimap is sorted. Thus we can
|
||||||
|
// stop checking the subsequent timers.
|
||||||
if (it->first > current) {
|
if (it->first > current) {
|
||||||
res = it->first - current;
|
res = it->first - current;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger the timer.
|
// Save and remove the timer because timer_event() call might delete
|
||||||
it->second.sink->timer_event (it->second.id);
|
// exactly this timer and then the iterator will be invalid.
|
||||||
}
|
timer_temp = it->second;
|
||||||
|
_timers.erase (it);
|
||||||
|
|
||||||
// Remove them from the list of active timers.
|
// Trigger the timer.
|
||||||
_timers.erase (begin, it);
|
timer_temp.sink->timer_event (timer_temp.id);
|
||||||
|
|
||||||
|
} while (!_timers.empty ());
|
||||||
|
|
||||||
// Return the time to wait for the next timer (at least 1ms), or 0, if
|
// Return the time to wait for the next timer (at least 1ms), or 0, if
|
||||||
// there are no more timers.
|
// there are no more timers.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user