Skip to content

Commit 154003e

Browse files
authored
async: remove inter-task wakeup stream from its waitable set before cancelling (#1638)
`cancel_inter_task_stream_read` issued a synchronous `stream.cancel-read` on the inter-task wakeup stream while that stream was still a member of the task's waitable set, only calling `remove_waitable` afterwards. Per the Component Model (component-model#647), a synchronous `{stream,future}.cancel-{read,write}` traps if the waitable is still in a waitable set, for the same reason synchronous reads/writes do. Runtimes that enforce this trap (e.g. recent Wasmtime) therefore fault here during ordinary async operation. Reorder so the stream leaves the waitable set before the synchronous cancel, matching the unregister-then-cancel ordering already used by the general `WaitableOperation::cancel` path. The cancel result is discarded as before, so behavior is otherwise unchanged.
1 parent cfd7b77 commit 154003e

1 file changed

Lines changed: 5 additions & 1 deletion

File tree

crates/guest-rust/src/rt/async_support/inter_task_wakeup.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,17 @@ impl FutureState<'_> {
5757
}
5858
self.inter_task_wakeup.stream_reading = false;
5959
let handle = self.inter_task_wakeup.stream.as_mut().unwrap().handle();
60+
// Remove the stream from our waitable set before cancelling. A
61+
// synchronous `stream.cancel-read` traps if the stream is still a member
62+
// of a waitable set, so this must happen first. This matches the
63+
// unregister-then-cancel ordering in `WaitableOperation::cancel`.
64+
self.remove_waitable(handle);
6065
// Note that the return code here is discarded. No matter what the read
6166
// is cancelled, and whether we actually read something or whether we
6267
// cancelled doesn't matter.
6368
unsafe {
6469
UnitStreamOps.cancel_read(handle);
6570
}
66-
self.remove_waitable(handle);
6771
}
6872
}
6973

0 commit comments

Comments
 (0)