Replies: 3 comments 3 replies
-
Here's a minimal example of the issue for those unfamiliar with this: #[tokio::main(flavor = "current_thread")]
async fn main() {
for i in 1..=129 {
let (tx, rx) = tokio::sync::oneshot::channel();
tx.send(()).unwrap();
tokio::select! {
biased;
_ = rx => {}
_ = futures::future::ready(()) => panic!("should not hit this: {} iters", i),
}
}
}
|
Beta Was this translation helpful? Give feedback.
-
I believe the reason that polling a It's certainly possible that it's not desirable for oneshots to do this, but I'm pretty sure that was the motivation. |
Beta Was this translation helpful? Give feedback.
-
There's been a long-standing bug in Tower that we recently tracked down to some very surprising behavior in
tokio::sync::oneshot
. Basically, we have an assumption that if aoneshot::Sender
has sent a value, then it must be observable by theoneshot::Receiver
. But this assumption is violated by Tokio's cooperative scheduling, which can sporadically cause aoneshot::Receiver::poll
to return Pending even though a value has been sent. The solution to this issue is to wraponeshot::Receiver
withtokio::task::unconstrained
so that its polls are not impacted by budgeting. This behavior is subtle, implicit, and undocumented--it seems extremely likely that there are other similar bugs lurking anywhere aoneshot
is used for synchronization.In my view, this dramatically undermines the utility of
oneshot
as a synchronization primitive.While I understand the goals of cooperative scheduling task budgeting, I don't understand what this approach protects against in the case of
oneshot
. A receiver:What problems would arise if we changed
oneshot
's behavior to stop participating in task budgeting?Beta Was this translation helpful? Give feedback.
All reactions