Evolve the wasip3 async C ABI for tasks#1637
Open
alexcrichton wants to merge 3 commits into
Open
Conversation
This commit is an evolution of the C ABI used to managed task-related infrastructure in WASIp3 with the goal of solving bytecodealliance#1618. The basic problem of bytecodealliance#1618 is that waitables in Rust aren't guaranteed to be polled within the context of the original task. For example by mixing an `async` Rust export and `block_on` it's possible to "cross the wires" and poll in one context while dropping/completing in another context. This can lead to buggy situations where a waitable is left in a set, not added to an appropriate set, or generally mis-managed. The solution here is to enhance the current C ABI of task management with clone/drop operations. Notably this enables waitables to retain a strong reference to the task state as opposed to always consulting what the current task in. This fixes a few situations such as: * When dropping a half-finished waitable it no longer needs to be dropped in the context of the original task. Dropping will unregister the waitable from a task that it was originally registered with. * When a waitable is moved from one task to another it needs to implicitly de-register with the previous task, and this was not previously done. Now with a retained strong reference it's able to clear out previous state upon re-registering with a new task. This change requires some finesse as this needs to be ABI-stable to work with previous versions of the `wit-bindgen` crate. The runtime support additionally can't assume that the new ABI bits are available and instead needs to handle the previous ABI as well. Not too too bad, in the end, though. This additionally did some refactoring of the state associated with async tasks to juggle things around and better represent the raw pointers/`Arc`/etc from before. Closes bytecodealliance#1618
dicej
approved these changes
Jun 17, 2026
| pub struct wasip3_task_vtable { | ||
| /// Currently `WASIP3_TASK_V2` as that was the first version that specified | ||
| /// vtables. | ||
| pub version: u32, |
Collaborator
There was a problem hiding this comment.
Why do we need a version field here and also in wasip3_task?
Member
Author
There was a problem hiding this comment.
My thinking was that this vtable would grow over time independent of the original wasip3_task but that might be a bit too overeager thinking on my part. Does that sound reasonable?
Collaborator
There was a problem hiding this comment.
I don't have strong feelings, but I would imagine that the one in wasip3_task could cover everything, including the vtable.
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.
This commit is an evolution of the C ABI used to managed task-related infrastructure in WASIp3 with the goal of solving #1618. The basic problem of #1618 is that waitables in Rust aren't guaranteed to be polled within the context of the original task. For example by mixing an
asyncRust export andblock_onit's possible to "cross the wires" and poll in one context while dropping/completing in another context. This can lead to buggy situations where a waitable is left in a set, not added to an appropriate set, or generally mis-managed.The solution here is to enhance the current C ABI of task management with clone/drop operations. Notably this enables waitables to retain a strong reference to the task state as opposed to always consulting what the current task in. This fixes a few situations such as:
This change requires some finesse as this needs to be ABI-stable to work with previous versions of the
wit-bindgencrate. The runtime support additionally can't assume that the new ABI bits are available and instead needs to handle the previous ABI as well. Not too too bad, in the end, though.This additionally did some refactoring of the state associated with async tasks to juggle things around and better represent the raw pointers/
Arc/etc from before.Closes #1618