Track whether there are any async tasks in a store#13246
Merged
alexcrichton merged 2 commits intobytecodealliance:mainfrom May 1, 2026
Merged
Track whether there are any async tasks in a store#13246alexcrichton merged 2 commits intobytecodealliance:mainfrom
alexcrichton merged 2 commits intobytecodealliance:mainfrom
Conversation
dicej
approved these changes
May 1, 2026
This commit adds a new API to `Accessor` to learn whether there are any async tasks that are "interesting" in a store. This is borne out of many discussions over the past few weeks amongst a number of folks where the basic problem is that for WASIp3 HTTP guests there's no way right now to send a signal of "keep me alive after I send my response" because that's post-return-style work. In WASIp2 this was modeled where the outparam that was passed in was set, and then work was done before returning. With WASIp3, however, a response is sent by returning which means that this is no longer possible. The general idea is that Wasmtime will now consider all tasks which have not yet exited as "interesting". These tasks in theory mean that the store should be kept alive as the guest still has work to complete. Note that tasks first return, and then exit, and they're still considered interesting after returning before they exit. In the future it's expected that the component model might have an ABI option to say "this task, by default, isn't interesting" with an opt-in method at runtime of saying "ok wait but yes this is interesting". In this manner it's expected that not all tasks for all of time will be considered interesting, only those that are intentionally opted-in to being interesting (and today that just so happens to be all of them). The API itself on `Accessor` is a `poll_*`-style function which enables both checking to see if there are no more tasks remaining as well as registering a callback to get notified when there are actually no more tasks remaining. In this manner HTTP servers can await this as one of the events that concludes when a guest is finished processing. The implementation of this API required some refactoring of `concurrent.rs`. Namely I wanted to have a relatively "narrow waist" through which increments/decrements of this internal counter happened to ensure that nothing was forgot. This is a bit non-trivial because there are a number of situations which means that a task is "exited", such as: * A synchronously lifted function returns. * An asynchronously lifted function returns `CALLBACK_CODE_EXIT`. * An asynchronously lifted function is stuck in the `STARTING` state, and then gets cancelled. * A task is running, is then cancelled, acknowledges the cancellation, and then exits. * A task with threads exits without actually returning, and then one of its threads returns for it. For now the logic of "are interesting tasks done" is now hooked into `cleanup_thread`. This will likely require adjusting in the future for threads because in this last bullet the `task.return` invocation is the point where all conditions are met (main thread exited, task returned) as opposed to when the thread itself exits. For now though this is intended to be as close an approximation as possible. Throughout this implementation I've performed a number of refactorings to reduce duplication, shuffle where methods are implemented, reduce some verbosity, etc. There are debug assertions in place for if this predicate ever goes wrong, which is intended to assist during development.
9b895de to
ac2c3e0
Compare
Now that their lifetime is extended they need to be included in this calculation.
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 adds a new API to
Accessorto learn whether there are any async tasks that are "interesting" in a store. This is borne out of many discussions over the past few weeks amongst a number of folks where the basic problem is that for WASIp3 HTTP guests there's no way right now to send a signal of "keep me alive after I send my response" because that's post-return-style work. In WASIp2 this was modeled where the outparam that was passed in was set, and then work was done before returning. With WASIp3, however, a response is sent by returning which means that this is no longer possible.The general idea is that Wasmtime will now consider all tasks which have not yet exited as "interesting". These tasks in theory mean that the store should be kept alive as the guest still has work to complete. Note that tasks first return, and then exit, and they're still considered interesting after returning before they exit. In the future it's expected that the component model might have an ABI option to say "this task, by default, isn't interesting" with an opt-in method at runtime of saying "ok wait but yes this is interesting". In this manner it's expected that not all tasks for all of time will be considered interesting, only those that are intentionally opted-in to being interesting (and today that just so happens to be all of them).
The API itself on
Accessoris apoll_*-style function which enables both checking to see if there are no more tasks remaining as well as registering a callback to get notified when there are actually no more tasks remaining. In this manner HTTP servers can await this as one of the events that concludes when a guest is finished processing.The implementation of this API required some refactoring of
concurrent.rs. Namely I wanted to have a relatively "narrow waist" through which increments/decrements of this internal counter happened to ensure that nothing was forgot. This is a bit non-trivial because there are a number of situations which means that a task is "exited", such as:CALLBACK_CODE_EXIT.STARTINGstate, and then gets cancelled.For now the logic of "are interesting tasks done" is now hooked into
cleanup_thread. This will likely require adjusting in the future for threads because in this last bullet thetask.returninvocation is the point where all conditions are met (main thread exited, task returned) as opposed to when the thread itself exits. For now though this is intended to be as close an approximation as possible.Throughout this implementation I've performed a number of refactorings to reduce duplication, shuffle where methods are implemented, reduce some verbosity, etc. There are debug assertions in place for if this predicate ever goes wrong, which is intended to assist during development.