-
Notifications
You must be signed in to change notification settings - Fork 635
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
Missed wake call using .shared()
#2706
Comments
Some initial thought for a potential fix: Add some additional (3 states) state enum next to the Right before calling the inner future’s Then after the call to the inner future’s
This way, a thread that observes the In more detail: The previously problematic setting was when a This setting means that first the polling thread records “inside inner poll” state, and then the poll happening during execution of the inner poll will put it into “woken while inside inner poll” state. Then the problematic thread calls I guess there’s some leeway implementation on the point whether a Perhaps more importantly, I have not thought about panic case(s) yet. Those would presumably also need to be handled somewhat properly. |
Trying to start an implementation of a fix, I came across a design question where I’m not sure what the best solution should be. If the The possible solution is to make sure to wake all other wakers in case of panic, so they have a chance to learn of the panicking Now the problem with this approach: Calling a bunch of wakers in a So really TL;DR, how bad are missed wake-ups in cases where panics happened somewhere? (I suppose bad enough that they do warrant a fix.) And how seriously should the case of panicking wakers be considered? (I’m unsure on this, and interested in hearing about guidelines or prior art on the question of panicking wakers.) |
Wanted to pop in and say thank you for working on this issue. I went down a rabbithole today debugging an application that uses |
Thanks for working on this!
It is not ideal, but fine. (Shared is neither UnwindSafe nor RefUnwindSafe. And IMO, a potential abort is bad anyway.)
I do not know of any prior art or guidelines for this particular case, but tokio-rs/tokio#3689 is somewhat relevant. |
any update or workaround for this issue? |
This is the reproduction:
It manages to hang up eventually on most runs, both in debug and release mode.
The example is crafted to expose a weakness spotted during code review of
.shared()
. The problematic part is here:futures-rs/futures-util/src/future/future/shared.rs
Lines 288 to 293 in aa1f5c7
This code is simply insufficient to ensure the current
context
’s waker is actually ever woken up. The current context’s waker was stored into the inner slab previously in this linefutures-rs/futures-util/src/future/future/shared.rs
Line 277 in aa1f5c7
However, a concurrently running
poll
could have already been within the call to the innerpoll
before the new waker got registered, i.e. here:futures-rs/futures-util/src/future/future/shared.rs
Line 328 in aa1f5c7
As soon as the call to
poll
on the inner future starts, it could already be calling the waker, thus doing the waking before the new waker that we care about was registered and put into the slab in the first place, because the waking could happen before the state is put back intoIDLE
.The waking could happen before the state is put back into
IDLE
in particular because it is okay for a.poll
call to do the waking immediately, before it returns, i.e the way theyield_now
function in the example always does (copied from the oldyield_now
implementation oftokio
).The text was updated successfully, but these errors were encountered: