taskdump: implement task dumps for current-thread runtime (#5608)

Task dumps are snapshots of runtime state. Taskdumps are collected by
instrumenting Tokio's leaves to conditionally collect backtraces, which
are then coalesced per-task into execution tree traces.

This initial implementation only supports collecting taskdumps from
within the context of a current-thread runtime, and only `yield_now()`
is instrumented.
This commit is contained in:
Jack Wrenn
2023-04-27 12:59:20 +02:00
committed by GitHub
parent 1d785fd66f
commit 660eac71f0
23 changed files with 943 additions and 13 deletions
+4
View File
@@ -90,3 +90,7 @@ path = "named-pipe-ready.rs"
[[example]]
name = "named-pipe-multi-client"
path = "named-pipe-multi-client.rs"
[[example]]
name = "dump"
path = "dump.rs"
+50
View File
@@ -0,0 +1,50 @@
//! This example demonstrates tokio's experimental taskdumping functionality.
#[cfg(all(
tokio_unstable,
tokio_taskdump,
target_os = "linux",
any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")
))]
#[tokio::main(flavor = "current_thread")]
async fn main() {
use std::hint::black_box;
#[inline(never)]
async fn a() {
black_box(b()).await
}
#[inline(never)]
async fn b() {
black_box(c()).await
}
#[inline(never)]
async fn c() {
black_box(tokio::task::yield_now()).await
}
tokio::spawn(a());
tokio::spawn(b());
tokio::spawn(c());
let handle = tokio::runtime::Handle::current();
let dump = handle.dump();
for (i, task) in dump.tasks().iter().enumerate() {
let trace = task.trace();
println!("task {i} trace:");
println!("{trace}");
}
}
#[cfg(not(all(
tokio_unstable,
tokio_taskdump,
target_os = "linux",
any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")
)))]
fn main() {
println!("task dumps are not available")
}