-
Notifications
You must be signed in to change notification settings - Fork 33
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
proxy_instance_serial_ws() uses select!
with non-cancel-safe future(s)
#3356
Comments
select!
with a non-cancel-safe future(s)select!
with non-cancel-safe future(s)
Indeed |
I think the best solution here is to define a version of |
Current status:
|
This allows arbitrary Sink combinators, and in particular the combinators in cancel-safe-futures, to be used against InstanceSerialConsoleHelper. This should not be disruptive to most users since the send(item) API removed here matches the futures::SinkExt::send(item) API exactly -- at most, they'll have to import futures::SinkExt. This is required as part of the fix for oxidecomputer/omicron#3356.
Use the cancel-safe adapters defined in https://github.com/oxidecomputer/cancel-safe-futures to ensure that the branches of the select loop are all cancel-safe. See #3356 for a detailed description of what's going on here.
The remaining uses have been tackled in #3411. We should be good with respect to cancel safety now. |
In
proxy_instance_serial_ws()
, we construct four futures over which we willtokio::select!
. In any given loop iteration, at least two of the futures are instances ofFuse::terminated()
(and therefore ignored byselect!
). The possible combinations of non-Fuse::terminated()
futures are:nexus_read
(aStreamExt::next()
future) andnexus_write
(aSinkExt::send()
future)nexus_read
andpropolis_read
(a future fromInstanceSerialConsoleHelper::recv()
in propolis)propolis_write
(a future fromsupport::send
in propolis which is a wrapper aroundSinkExt::send()
) alonepropolis_write
andnexus_write
Case 3 is fine because there is only one possible future for
select!
to choose, so there is no possibility for cancellation. But in the other three cases,select!
will cancel one of the two futures once it chooses one. In terms of cancel safety, none of these futures is explicitly documented; however:StreamExt::next()
is cancel safe, because the equivalent method in tokio-stream's StreamExt is explicitly documented as cancel safe.SinkExt::send()
is not cancel safe: ifselect!
ing over aSinkExt::send()
future and a different arm is chosen, the item being sent to the sink will be lost. (A reproducer; I'll also file an issue onfutures-util
to confirm / try to get it documented. EDIT: filed Documenting cancel safety ofSinkExt::send()
rust-lang/futures-rs#2754)InstanceSerialConsoleHelper::recv()
is cancel safe, but based on it containing multiple.await
points I suspect it is not: if an item is pulled out ofself.ws_stream
and the future is dropped at a later await point, I believe the item will be lost.I'm not sure at the moment how to address this; I'm just skimming through omicron's
select!
s looking for suspicious cancel safety issues. CC @lifningThe text was updated successfully, but these errors were encountered: