2个版本
0.1.1 | 2023年7月31日 |
---|---|
0.1.0 | 2023年7月30日 |
#1361 in 异步
17KB
108 代码行
tasktrace
异步函数的逻辑'栈'跟踪。
此crate允许您捕获正在运行的异步任务的堆栈跟踪。
用法
要使用,使用tasktrace::traced
将您感兴趣的future(通常是顶层future)包装起来,并使用返回的句柄在任何时候请求堆栈跟踪。
#[tokio::main]
async fn main() {
let (foo_fut, trace_handle) = tasktrace::traced(foo());
tokio::spawn(foo_fut);
println!("{}", trace_handle.backtrace().await.unwrap());
}
async fn pending() {
let mut waker = None;
std::future::poll_fn(|cx| {
// Pretend to stash the waker for some future time like a real leaf Future would do.
// This is what records the stacktrace.
waker = Some(cx.waker().clone());
std::task::Poll::Pending
}).await
}
async fn foo() {
bar().await;
}
async fn bar() {
tokio::join!(fiz(), buz());
}
async fn fiz() {
pending().await;
}
async fn buz() {
baz().await;
}
async fn baz() {
pending().await;
}
此示例程序将打印出类似以下内容:
╼ <tasktrace::TracedTask<F> as core::future::future::Future>::poll::{{closure}} at /home/petrosagg/projects/tasktrace/src/lib.rs:116:50
└╼ taskdump::foo::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:18:11
└╼ taskdump::bar::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:22:5
└╼ <tokio::future::poll_fn::PollFn<F> as core::future::future::Future>::poll at /home/petrosagg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/future/poll_fn.rs:58:9
├╼ taskdump::bar::{{closure}}::{{closure}} at /home/petrosagg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/macros/join.rs:126:24
│ └╼ <tokio::future::maybe_done::MaybeDone<Fut> as core::future::future::Future>::poll at /home/petrosagg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/future/maybe_done.rs:68:48
│ └╼ taskdump::fiz::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:26:15
│ └╼ taskdump::pending::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:14:8
│ └╼ <core::future::poll_fn::PollFn<F> as core::future::future::Future>::poll at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/future/poll_fn.rs:64:9
│ └╼ taskdump::pending::{{closure}}::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:12:22
│ └╼ <core::task::wake::Waker as core::clone::Clone>::clone at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/task/wake.rs:342:29
│ └╼ tasktrace::clone_raw at /home/petrosagg/projects/tasktrace/src/lib.rs:135:5
└╼ taskdump::bar::{{closure}}::{{closure}} at /home/petrosagg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/macros/join.rs:126:24
└╼ <tokio::future::maybe_done::MaybeDone<Fut> as core::future::future::Future>::poll at /home/petrosagg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/future/maybe_done.rs:68:48
└╼ taskdump::buz::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:30:11
└╼ taskdump::baz::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:34:15
└╼ taskdump::pending::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:14:8
└╼ <core::future::poll_fn::PollFn<F> as core::future::future::Future>::poll at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/future/poll_fn.rs:64:9
└╼ taskdump::pending::{{closure}}::{{closure}} at /home/petrosagg/projects/tasktrace/examples/taskdump.rs:12:22
└╼ <core::task::wake::Waker as core::clone::Clone>::clone at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/task/wake.rs:342:29
└╼ tasktrace::clone_raw at /home/petrosagg/projects/tasktrace/src/lib.rs:135:5
工作原理
此crate利用了所有叶future都必须在稍后某个时间点克隆提供的上下文Waker才能调用它的事实。
当请求跟踪的future捕获调用栈时,它将正常waker包装成一个其Waker::clone
方法被设置为捕获堆栈跟踪的waker。由于只有叶future会交互和克隆waker,因此堆栈跟踪将必然包含所需的调用栈。
如果正在等待多个future(例如,通过select!
),则将为每个轮询的future捕获多个堆栈跟踪,并将它们的组合堆栈跟踪显示为树形结构。
依赖关系
~3.5–4.5MB
~90K SLoC