-
-
Notifications
You must be signed in to change notification settings - Fork 18
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async Rust support #37
Comments
Woo, awesome work! Does this mean we are getting closer to seeing this in a release version of FireDBG? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How can we support debugging async Rust? As it is basically impossible to use a step debugger.
First off, the background. Async Rust has a runtime. The runtime manages a number of async tasks, called
Future
. Each Future is a state machine (the complex part is it is hierarchical), and it can only progress by having someone polling it. From an instruction point of view, each async function is a block of code ("closure") that can be reentered an unknown number of times. There is a context associated with this future, and our goal is to track the lifecycle of each Future, from create to drop, and every time it makes progress. Every await point is a yield point, meaning the closure returns, and the state machine may or may not have a state transition.Static analysis already tells us whether a function is async. (it is actually quite tricky to derive this from looking at the assembly).
I think we can model the event stream in FireDBG just like regular functions, but with an additional async context pointer. At any given point in time, the pointer should uniquely identifies a Future. But we also need to hook into the Future lifecycle and record the "async context create" and "async context destroy" events. The
Pin
semantic ensures that once a Future is being polled, it stays in place in memory. Then we should have enough information to reconstruct an async timeline. Hierarchical async functions shares the same async context, so they can be uniquely identified by (async context, function address).Constructing a call tree requires parent-child relation. We need to identify the "true" parent of an async function on runtime.
We have to be aware of
b
,c
both being children ofa
, instead ofa -> b -> c
if we naively look at the sequence of events. At least in the above case, we can reconstruct the async call stack by looking at the real stack trace:It should be doable to capture the parameters of an async function on first call, but I couldn't think of a way to capture the return value (yet).
Reference: https://fitzgeraldnick.com/2019/08/27/async-stacks-in-rust.html
The text was updated successfully, but these errors were encountered: