scaled range timer: guard against queue deletion during timer fire#14799
scaled range timer: guard against queue deletion during timer fire#14799ggreenway merged 4 commits intoenvoyproxy:mainfrom
Conversation
…ssing a callback Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com>
Add a `processing_timers_` flag to the timer queues that is set during `onQueueTimerFired` processing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered by `onQueueTimerFired`. Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com>
|
cc @akonradi |
|
Sweet, thanks for the fix! |
| timer1->enableTimer(std::chrono::seconds(100)); | ||
| timer2->enableTimer(std::chrono::seconds(100)); |
There was a problem hiding this comment.
Since these timers are enabled for the same duration, they can fire in either order. Consider making timer1 fire in 95 seconds with an absolute minimum of 0.
There was a problem hiding this comment.
We need both timers to end up in the same queues so their durations should be the same.
I think the solution is to do an advance of 5 seconds between the first enable and the second enable.
There was a problem hiding this comment.
Either of those will work. The duration that matters is (max - min) which is (100 - 5) or (95 - 0) as adjusted.
Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com>
| queue.range_timers_.pop_front(); | ||
| item.timer_.trigger(); | ||
| } | ||
| queue.processing_timers_ = false; |
There was a problem hiding this comment.
So processing_timers_ needs to be per queue since otherwise the queue not empty invariant would not hold if a timer from queue A removes a timer from queue B. It would be good to also cover that case in tests.
Also, is there code somewhere that verifies the invariant that all active queues are non-empty?
There was a problem hiding this comment.
Also, is there code somewhere that verifies the invariant that all active queues are non-empty?
I don't believe there is currently. The number of queues and sizes is not currently exposed. I'm okay to keep this PR focused on the bugfix and add additional testing in a follow-on.
There was a problem hiding this comment.
023d9ec adds a test for cancelling a timer from a different queue in the context of a timer callback.
…ent queue Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com>
antoniovicente
left a comment
There was a problem hiding this comment.
Thanks for reporting this bug and providing a fix.
I would like to keep the issue you filed open until we manage to followup on some of the test improvements mentioned in various review comments.
|
Does this make sense as a candidate for a backport to 1.17? That is where I originally discovered this issue. |
|
Tagged for backport. @envoyproxy/senior-maintainers could one of you review the PR? |
|
ping @envoyproxy/senior-maintainers for review since previous mention was over the weekend. |
…nvoyproxy#14799) Fix a potential use-after-free error in ScaledRangeTimerManagerImpl by adding a processing_timers_ flag to the timer queues that is set during onQueueTimerFired processing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered by onQueueTimerFired. Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com> Signed-off-by: Shikugawa <rei@tetrate.io>
…nvoyproxy#14799) Fix a potential use-after-free error in ScaledRangeTimerManagerImpl by adding a processing_timers_ flag to the timer queues that is set during onQueueTimerFired processing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered by onQueueTimerFired. Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com> Signed-off-by: Shikugawa <rei@tetrate.io>
Signed-off-by: Alex Konradi <akonradi@google.com>
…g timer fire (#14799) (#15007) Fix a potential use-after-free error in ScaledRangeTimerManagerImpl by adding a processing_timers_ flag to the timer queues that is set during onQueueTimerFired processing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered by onQueueTimerFired. Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com> Signed-off-by: Shikugawa <rei@tetrate.io>
…g timer fire (#14799) (#15006) Fix a potential use-after-free error in ScaledRangeTimerManagerImpl by adding a processing_timers_ flag to the timer queues that is set during onQueueTimerFired processing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered by onQueueTimerFired. Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com> Signed-off-by: Shikugawa <rei@tetrate.io>
Commit Message:
Fix a potential use-after-free error in
ScaledRangeTimerManagerImplby adding aprocessing_timers_flag to the timer queues that is set duringonQueueTimerFiredprocessing. This flag is checked when a timer is removed to ensure that the timer's queue isn't deleted while it is in a callback triggered byonQueueTimerFired.Additional Description: N/A
Risk Level: Low - the issue does not appear possible in current Envoy code
Testing: unit test that reproduces the issue under ASAN
Docs Changes: N/A
Release Notes: N/A
Platform Specific Features: N/A
Issue #14798