Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Debugging: allow frame cursor to visit all activations.#12176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
cfallin wants to merge1 commit intobytecodealliance:main
base:main
Choose a base branch
Loading
fromcfallin:debugging-host-sandwich

Conversation

@cfallin
Copy link
Member

In the initial design for theDebugFrameCursor, I was concerned about the effects of host async on the stability of visiting earlier activations (see also the discussion of async combinators in#11896). The basic hypothesized problem was that when Wasm calls host-code calls Wasm, the sequence of activations on the stack is not even stable between async polls; so any debugger hook, which is an async function, should not be allowed to hold a frame cursor across a yield point since it could become invalidated if the next poll stacks up the activations differently.

In further conversations it's become clear that this is not actually a possibility, for the simple reason that the inner re-entrant activations into the same store take full ownership (mutably reborrow) that store, and that mut reborrow becomes part of the future; so the exact chain of activations will remain in the same sequence when re-polled. Said another way, it is impossible at any given level of async host-code to createmore than one future that re-enters the same store and somehow poll those in different orders at different times. The worst that a host-code async combinator can do is drop the future that re-enters the store. This drops and invalidates whatever frames a cursor held over a yield might be referencing, but italso drops the async invocation of the debugger hook itself, and due to lifetimes the cursor cannot escape that hook, so everything is still sound.

This PR thus updates theDebugFrameCursor to visit all activations. I've generalized the backtrace code a bit to enable this, and built an internalStoreBacktrace that is an iterator over all activations associated with the store.

At theDebugFrameCursor (public API) level, the two basic choices were to present a sentinel for host frame(s) explicitly and make all Wasm-specific accessors returnOption<T>, or skip over host frames. I opted for the latter, withmove_to_parent() returning an enum value now that indicates whether it moved to a new activation.

A note regarding theasync component ABI: once debugging is possible within arun_concurrent environment, it will again be the case that a single frame cursor should see only one activation, because each (re)-entry into the store becomes a new task, if my understanding is correct. At that time, we should build an API that lets the debugger see the activation for each task separately. That's a simpler model ultimately, and it will be nice when we move to it, but as long as we have the sync component ABI with async host code and the ability to stack activations as we do today, we need to provide the debugger this visibility.

(Aside: why does the debuggerneed to see more than one activation? In addition to presenting a weird and incoherent view of the world to the user if we don't, it is also necessary to implement the "next" (step-over) debugger action, because otherwise a call to a host function that re-enters the store may lead to a state with fewer, but completely disjoint, stack frames on the "one latest activation" from which it's not possible to reason about whether we've left the called-into function yet.)

@cfallincfallin requested a review froma team as acode ownerDecember 17, 2025 07:44
@cfallincfallinforce-pushed thedebugging-host-sandwich branch 2 times, most recently fromd5edc9c to286fa8dCompareDecember 17, 2025 07:47
In the initial design for the `DebugFrameCursor`, I was concernedabout the effects of host async on the stability of visiting earlieractivations (see also the discussion of async combinators inbytecodealliance#11896).The basic hypothesized problem was that when Wasm calls host-codecalls Wasm, the sequence of activations on the stack is not evenstable between async polls; so any debugger hook, which is an asyncfunction, should not be allowed to hold a frame cursor across a yieldpoint since it could become invalidated if the next poll stacks up theactivations differently.In further conversations it's become clear that this is not actually apossibility, for the simple reason that the inner re-entrantactivations into the same store take full ownership (mutably reborrow)that store, and that mut reborrow becomes part of the future; so theexact chain of activations will remain in the same sequence whenre-polled. Said another way, it is impossible at any given level ofasync host-code to create *more than one* future that re-enters thesame store and somehow poll those in different orders at differenttimes. The worst that a host-code async combinator can do is drop thefuture that re-enters the store. This drops and invalidates whateverframes a cursor held over a yield might be referencing, but it *also*drops the async invocation of the debugger hook itself, and due tolifetimes the cursor cannot escape that hook, so everything is stillsound.This PR thus updates the `DebugFrameCursor` to visit allactivations. I've generalized the backtrace code a bit to enable this,and built an internal `StoreBacktrace` that is an iterator over allactivations associated with the store.At the `DebugFrameCursor` (public API) level, the two basic choiceswere to present a sentinel for host frame(s) explicitly and make allWasm-specific accessors return `Option<T>`, or skip over hostframes. I opted for the latter, with `move_to_parent()` returning anenum value now that indicates whether it moved to a new activation.A note regarding the *async* component ABI: once debugging is possiblewithin a `run_concurrent` environment, it will again be the case thata single frame cursor should see only one activation, becauseeach (re)-entry into the store becomes a new task, if my understandingis correct. At that time, we should build an API that lets thedebugger see the activation for each task separately. That's a simplermodel ultimately, and it will be nice when we move to it, but as longas we have the sync component ABI with async host code and the abilityto stack activations as we do today, we need to provide the debuggerthis visibility.(Aside: why does the debugger *need* to see more than one activation?In addition to presenting a weird and incoherent view of the world tothe user if we don't, it is also necessary to implement the"next" (step-over) debugger action, because otherwise a call to a hostfunction that re-enters the store may lead to a state with fewer, butcompletely disjoint, stack frames on the "one latest activation" fromwhich it's not possible to reason about whether we've left thecalled-into function yet.)
@cfallincfallinforce-pushed thedebugging-host-sandwich branch from286fa8d to5107b56CompareDecember 17, 2025 07:50
@github-actionsgithub-actionsbot added the wasmtime:apiRelated to the API of the `wasmtime` crate itself labelDec 17, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fitzgenfitzgenAwaiting requested review from fitzgen

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

wasmtime:apiRelated to the API of the `wasmtime` crate itself

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

@cfallin

[8]ページ先頭

©2009-2025 Movatter.jp