-
Notifications
You must be signed in to change notification settings - Fork 127
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
Bug: Race condition in next_when_notified #280
base: master
Are you sure you want to change the base?
Bug: Race condition in next_when_notified #280
Conversation
@mzabaluev you're probably best placed for an opinion |
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! My original code overlooked this possibility.
I have suggestions to improve the comments, otherwise the fix is good.
// In the single-threaded case, no buffers could get checked in | ||
// between us calling `try_next` and here, so we can't miss a wakeup. | ||
notified.as_mut().await; | ||
// between us calling `try_next` and here. However, we may still miss a wake-up, | ||
// as multiple check-ins can occur before any waking tasks are scheduled, | ||
// which would result in the loss of a permit |
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.
This is right, thanks for the clarification. In fact, the preamble of this comment can be completely replaced because it's irrelevant: multiple buffers can still be checked in while awaiting on notified
before another iteration of the loop.
@@ -284,6 +286,9 @@ impl<T: IoBufMut> FixedBufPool<T> { | |||
return buf; | |||
} | |||
|
|||
// Await notify_one | |||
notified.as_mut().await; | |||
|
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.
I think the comment below clarifies why the whole branch below the if ... { ... return buf; }
can be taken, so part of it should be placed above this.
I believe the following fixes a race condition in
FixedBufPool
. We were observing a situation where, without resorting to timeouts to force retries, multiple concurrent calls to next would eventually all stall.The fix (setting enable) is take directly from https://docs.rs/tokio/latest/tokio/sync/futures/struct.Notified.html#method.enable
I believe this is happening in the presence of only concurrency, not parallelism (single threaded)