component model: drop borrows when cancelling host tasks - #12631
Closed
jellevandenhooff wants to merge 1 commit into
Closed
component model: drop borrows when cancelling host tasks#12631jellevandenhooff wants to merge 1 commit into
jellevandenhooff wants to merge 1 commit into
Conversation
jellevandenhooff
requested review from
alexcrichton
and removed request for
a team
February 20, 2026 23:07
Per the component-model spec, "a resolved subtask has always dropped all the borrowed handles that it was lent during the call" (Concurrency.md). In the reference interpreter, `Subtask.deliver_resolve` decrements the `num_lends` counts before the resolution event reaches the caller. When an async-lowered host function borrows a resource, `resource_lift_borrow` increments the lend count on the owned resource and records the lender in the host task's `CallContext`. Normally `validate_scope_exit` undoes these lends when the task completes, but `subtask.cancel` aborted the join handle without going through that path. Add `ResourceTables::cancel_scope` to release outstanding lends for a cancelled host task, and call it from `subtask_cancel` after aborting the join handle. A new test (`cancel_host_task_releases_borrow`) exercises this by creating an owned resource, lending it to an async host function, cancelling the subtask, and then dropping the resource.
jellevandenhooff
force-pushed
the
fix-subtask-cancel-borrow-release
branch
from
February 20, 2026 23:16
5407eb5 to
bb386c7
Compare
Member
|
Thanks for the PR! Definitely looks like wrong behavior here, especially as the test shows. The fix isn't quite what I would have in mind for this, however, so I'll work a bit locally to see if I can't get something working. I'll likely have a sibling PR to this which includes your test as well. Will post back here when that's ready. |
alexcrichton
added a commit
to alexcrichton/wasmtime
that referenced
this pull request
Feb 23, 2026
This commit refactors some of the internals of `subtask.cancel` with respect to host subtasks. Notably a few panics and semantic bugs are fixed here. The main bug was that host subtasks could be aborted but their completion might have still been queued up which would produce the result somewhere or assert that the task exists. Cancellation is changed to use `wait_for_event` to ensure that this completion is executed before `subtask.cancel` returns. This helps keep host subtasks looking more similar to guest subtasks in that respect. Co-authored-by: Jelle van den Hooff <jelle@vandenhooff.name> Closes bytecodealliance#12631 Closes bytecodealliance#12632
alexcrichton
added a commit
to alexcrichton/wasmtime
that referenced
this pull request
Feb 23, 2026
This commit refactors some of the internals of `subtask.cancel` with respect to host subtasks. Notably a few panics and semantic bugs are fixed here. The main bug was that host subtasks could be aborted but their completion might have still been queued up which would produce the result somewhere or assert that the task exists. Cancellation is changed to use `wait_for_event` to ensure that this completion is executed before `subtask.cancel` returns. This helps keep host subtasks looking more similar to guest subtasks in that respect. Closes bytecodealliance#12631 Closes bytecodealliance#12632 Co-authored-by: Jelle van den Hooff <jelle@vandenhooff.name>
Member
|
Ok I've pushed up a "more official fix" to #12640 which includes the tests here and should resolve them. Thanks again @jellevandenhooff! |
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Feb 23, 2026
This commit refactors some of the internals of `subtask.cancel` with respect to host subtasks. Notably a few panics and semantic bugs are fixed here. The main bug was that host subtasks could be aborted but their completion might have still been queued up which would produce the result somewhere or assert that the task exists. Cancellation is changed to use `wait_for_event` to ensure that this completion is executed before `subtask.cancel` returns. This helps keep host subtasks looking more similar to guest subtasks in that respect. Closes #12631 Closes #12632 Co-authored-by: Jelle van den Hooff <jelle@vandenhooff.name>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Update the component model resource tracking to handle cancelling host tasks. Before this change, when cancelling a read on a UDP socket and then dropping the socket failed because of outstanding borrows: the read never released its borrow. Now it does.
I debugged this issue and wrote the code with Claude. I've tested this code for my use case and it seems to work, but I don't fully understand the implications. I worry that it might not be safe to release the borrow count because maybe the host function can still run.