-
Notifications
You must be signed in to change notification settings - Fork 5.1k
scaled range timer: guard against queue deletion during timer fire #14799
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
scaled range timer: guard against queue deletion during timer fire #14799
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
while (!timers.empty() && | ||
computeTriggerTime(timers.front(), queue.duration_, scale_factor_) <= now) { | ||
auto item = std::move(queue.range_timers_.front()); | ||
queue.range_timers_.pop_front(); | ||
item.timer_.trigger(); | ||
} | ||
queue.processing_timers_ = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
023d9ec adds a test for cancelling a timer from a different queue in the context of a timer callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…ent queue Signed-off-by: Craig Radcliffe <craig.radcliffe@broadcom.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
ScaledRangeTimerManagerImpl
by adding aprocessing_timers_
flag to the timer queues that is set duringonQueueTimerFired
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 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