Fix wasip3 blocking UDP subtask handle leaks - #868
Conversation
On wasip3, blocking recv/send that wait for a pending subtask must drop the component-model handle when the wait completes. The nonblocking paths already did this; the blocking success paths only cleared the handle field and leaked. - recv: call wasip3_recv_end after a successful wait (drop + clear) - send: do not zero send_subtask before the shared drop block - Add dual-process blocking UDP roundtrip suite test (64 cycles)
alexcrichton
left a comment
There was a problem hiding this comment.
Thanks! Locally I'm seeing the test pass both before and after this change -- would it be possible to write the test such that it fails beforehand and passes afterwards?
I/O-only roundtrips pass with or without subtask drop because the payload is already in guest storage after wait. Cap wasmtime concurrent resources (-Smax-resources=128) on the dual-process suite so undropped HostTask entries fail with "resource table has no free keys" while a correct drop stays under the cap. Raise rounds to 200 and timeout to 15s.
|
Thanks for catching that, Alex. You are right: a pure send/recv correctness test cannot fail on this bug. After a successful blocking wait the datagram (or send completion) is already in guest-side storage, so clearing I pushed a stronger red/green setup on the dual-process suite:
Rounds are 200 and the harness timeout is 15s for that test. wasip2 is unchanged (no async subtasks on this path). If 128 is too tight for baseline wasip3 CLI/socket bookkeeping on some runners, we can raise the cap slightly while keeping N large enough that a one-leak-per-completion path still trips it. |
Summary
On wasip3, when a blocking UDP
recv/sendwaits for a pendingcomponent-model subtask and the wait completes, the handle must be
dropped. The nonblocking paths already do this. The blocking success
paths only cleared the field and leaked the handle.
wasip3_recv_endafter a successful wait (same as thenonblocking path)
send_subtaskbefore the sharedwasip3_subtask_dropblock so that drop actually runsblocks in
recvfrombefore each client send so a pending receivesubtask is common
Timeout paths still leave the subtask in place for a later retry.
Origin
Introduced in #775 (2026-04-03) when nonblocking UDP I/O was added.
Related
wasip3_recv_end/ shared send drop