Stream: git-wasmtime

Topic: wasmtime / PR #14461 wasi: restore cancellation of pendin...


view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 01:58):

macovedj opened PR #14461 from macovedj:wasi-p2-tcp-drop to bytecodealliance:main:

Dropping a WASIp2 TCP output stream can deadlock when a pending write needs the peer to read and the guest drops the sender before reading the receiver. The comment added in #13934 explains that cancellation waits for write readiness to preserve accepted data, but I couldn’t find discussion of this deadlock scenario.

This PR restores abort-and-wait cancellation by stopping pending writes and waiting for their cleanup before returning. When shutdown wraps a pending write, we abort that write and join its cleanup through the shutdown task. Idle and completed send streams remain owned by the parent socket.

The tradeoff is that dropping an unflushed stream may discard unfinished write data, which WASI explicitly permits. Explicit shutdown continues to drain writes while the output remains alive. Restoring the previous cancellation behavior seems preferable to allowing drop to deadlock, though I’d appreciate any context I’m missing about guarantees for pending writes that would make restoring the old behavior a problem.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 01:58):

macovedj requested pchickey for a review on PR #14461.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 01:58):

macovedj requested wasmtime-wasi-reviewers for a review on PR #14461.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 01:58):

macovedj requested wasmtime-core-reviewers for a review on PR #14461.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 02:58):

github-actions[bot] added the label wasi on PR #14461.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 19:18):

alexcrichton commented on PR #14461:

cc @badeend as you probably have thoughts on this as well -- without reviewing this too too deeply IIRC the thinking is that if writes are accepted then it's expected they'll make their way out at least eventually and it's a bit too surprising for them to get cancelled. It sounds like this PR is reversing that where accepted writes may still be cancelled?

view this post on Zulip Wasmtime GitHub notifications bot (Oct 01 2026 at 20:40):

macovedj commented on PR #14461:

That's accurate. Yeah that was also my take from the PR discussion, just not sure how to handle the tradeoff between making sure they end and avoiding the deadlock. After thinking on it bit more, I'm wondering if retaining the pending write in a background task may be a better alternative? That would preserve the current behavior and let the guest progress after the sender is dropped, though if the peer never reads then the task/socket could remain alive indefinitely.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 04 2026 at 09:51):

badeend commented on PR #14461:

From the guest's POV: when a write on a non-blocking TCP socket succeeds, it may reasonably expect for that write to _not_ get lost when closing the socket afterwards. That's how POSIX/BSD behaves, so changing those semantics in WASI would break existing applications.

That's the reason why we don't drop the write in wasmtime at the moment.

_However,_ the world has moved on since the p2 days. In https://github.com/WebAssembly/wasi-libc/pull/845, wasi-libc was updated to block on any in-progress writes when close'ing a socket. IIUC, that was changed for p3 streams only.
Maybe we can do a similar thing for p2 sockets too; issue a output-stream::blocking-flush when closing the socket. That way the guest can be guaranteed the write has been transfered over to the kernel, and does not depend on wasmtime's behavior.

That being said, I don't think we can merge this as-is right now without taking the appropriate precautions in wasi-libc first.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2026 at 15:39):

macovedj commented on PR #14461:

Thanks for clarifying why the successful-write guarantee needs to be preserved, @badeend.

The motivating case came from a Node-compatible runtime on WASI where both TCP peers shared the guest’s event loop. Synchronous close blocked that loop, preventing the peer from reading. We’ve addressed the hang by deferring close in the guest’s networking layer, allowing readers to continue running while accepted writes drain.

For others who encounter similar hangs, it’s unclear to me whether the proposed wasi-libc changes would resolve them, since a blocking flush would still wait for pending output during close, though maybe I'm missing something.

Given that, I’m happy for this PR to be closed without merging. I’m also happy to look into the P2 blocking-flush change in wasi-libc if that would be useful. If you see a way those changes would address this scenario, we could keep this PR open and revisit merging it once they land. Thanks for helping clarify this.


Last updated: Oct 11 2026 at 04:10 UTC