WebAssembly / WebAssembly/component-model
Add the ability for threads to manually set their "current task"
Nobody has claimed this yet.
- Dominant language
- WebAssembly
- Stars
- 1.4k
- Forks
- 130
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 15
Description
With Preview 3 concurrency, at all execution points, there is a well-defined async call stack that terminates at a call from the host into a component export. This async call stack is useful for runtime debugging/profiling/tracing scenarios but it also allows a host-implemented import to have a well-defined answer to "which host export call am I executing on behalf of" which is otherwise hard to answer when you're executing multiple concurrent tasks. For example, this information is useful for logging and proxy loop detection scenarios in WASI HTTP. In the future, the same information could be exposed to wasm, for virtualizaiton purposes, when a parent component donut wraps a child component.
One nice thing about the async call stack is that it is maintained automatically by default (even with cooperative threads) and so in many scenarios the import-to-export attribution will just work. However, if the guest code / guest runtime has its own in-wasm concurrency runtime/scheduler, it's possible that all component export calls end up funneling down to a single scheduler loop in which case the default async call stack will make it look like everything is coming from one root host call. At this point, there's little we can do automatically without some degree of help from the guest code.
One option is that we could provide a new CM built-in that allows the guest's concurrency runtime / scheduler to explicitly override the default-propagated async call stack with something better, based on the guest's own internal bookkeeping state. The simplest way I can think of to do this would be to add a built-in (say thread.set-task):
(func $thread.set-task (param $other-thread-index i32))
This would change the current thread's associated async call stack to be the same as some other thread. (In the CABI Python code, this would mostly just be current_thread().task = current_instance().threads[other-thread-index].task.) As background: each call to a component export mints a new i32 thread index (retrieved by that thread via thread.index). So then the guest concurrency runtime could record the thread.indexes of all new export calls and, using whatever guest-internal bookkeeping, call thread.set-task right before executing a work-item from the shared scheduler loop so that the scheduler thread executes "on behalf of" that work-item's associated export call.
With the addition of this built-in, we could also non-normatively document an expectation (like we did with the Component Instance lifetime section) that guest toolchains should ensure (via automatic propagation or manual thread.set-task) that import calls are "properly" attributed to export calls ("properly" in quotes b/c what that means is language-dependent). It's important to note that there's no way to formally define or enforce this expectation, so it's a cooperative, best-effort sort of thing and thus should not be used for security-sensitive discrimination between concurrent async export calls (which, if a component instance is being reused, would be a bad idea in any case). Logging and accident-mitigation are good use cases, though.
This all seems additive to what's already defined/implemented, so I don't think adding this built-in blocks the initial release of Preview 3, but it does seem like a good follow-up worth considering.
(I'm going to be on vacation for the next 2 weeks after tomorrow, so apologies in advance for slow replies.)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading design/mvp/Concurrency.md, especially the async call stack and TODO sections, then review the linked WASI logging and proxy-loop discussions for context. Determine where a proposed thread.set-task built-in and its non-normative guest-toolchain guidance belong in the component model design. Done means the design is agreed and the specification changes clearly define behavior and limitations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- wasm
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100