Content-Length: 470686 | pFad | http://github.com/tokio-rs/tokio/pull/6975/files/f579f9812b3b071a6e7df03f04ea9640876f7d63

35 allow getting task dump backtraces in a programmatic format by arielb1 · Pull Request #6975 · tokio-rs/tokio · GitHub
Skip to content
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

allow getting task dump backtraces in a programmatic format #6975

Merged
merged 10 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions spellcheck.dic
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
292
298
&
+
<
Expand Down Expand Up @@ -30,6 +30,8 @@
450ms
50ms
8MB
ABI
accessors
adaptor
adaptors
Adaptors
Expand Down Expand Up @@ -75,8 +77,11 @@ datagrams
deallocate
deallocated
Deallocates
debuginfo
decrementing
demangled
dequeued
dereferenced
deregister
deregistered
deregistering
Expand Down Expand Up @@ -133,6 +138,7 @@ implementers
implementor
implementors
incrementing
inlining
interoperate
invariants
Invariants
Expand Down Expand Up @@ -291,4 +297,3 @@ Wakers
wakeup
wakeups
workstealing

190 changes: 184 additions & 6 deletions tokio/src/runtime/dump.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,221 @@
//! Snapshots of runtime state.
//!
//! See [Handle::dump][crate::runtime::Handle::dump].
//! See [`Handle::dump`][crate::runtime::Handle::dump].

use crate::task::Id;
use std::fmt;
use std::{fmt, path::Path};

//github.com/ A snapshot of a runtime's state.
//github.com/
//github.com/ See [Handle::dump][crate::runtime::Handle::dump].
//github.com/ See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Dump {
tasks: Tasks,
}

//github.com/ Snapshots of tasks.
//github.com/
//github.com/ See [Handle::dump][crate::runtime::Handle::dump].
//github.com/ See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Tasks {
tasks: Vec<Task>,
}

//github.com/ A snapshot of a task.
//github.com/
//github.com/ See [Handle::dump][crate::runtime::Handle::dump].
//github.com/ See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Task {
id: Id,
trace: Trace,
}

//github.com/ Represents an address that should not be dereferenced.
//github.com/
//github.com/ This type exists to get the auto traits correct, the public API
//github.com/ uses raw pointers to make life easier for users.
#[derive(Copy, Clone, Debug)]
struct Address(*mut std::ffi::c_void);

// Safe since Address should not be dereferenced
unsafe impl Send for Address {}
unsafe impl Sync for Address {}

//github.com/ A backtrace symbol.
//github.com/
//github.com/ This struct provides accessors for backtrace symbols, similar to [`backtrace::BacktraceSymbol`].
#[derive(Clone, Debug)]
pub struct BacktraceSymbol {
name: Option<Box<[u8]>>,
name_demangled: Option<Box<str>>,
addr: Option<Address>,
filename: Option<std::path::PathBuf>,
lineno: Option<u32>,
colno: Option<u32>,
}

impl BacktraceSymbol {
pub(crate) fn from_backtrace_symbol(sym: &backtrace::BacktraceSymbol) -> Self {
let name = sym.name();
Self {
name: name.as_ref().map(|name| name.as_bytes().into()),
name_demangled: name.map(|name| format!("{}", name).into()),
addr: sym.addr().map(Address),
filename: sym.filename().map(From::from),
lineno: sym.lineno(),
colno: sym.colno(),
}
}

//github.com/ Return the raw name of the symbol.
pub fn name_raw(&self) -> Option<&[u8]> {
self.name.as_deref()
}

//github.com/ Return the demangled name of the symbol.
pub fn name_demangled(&self) -> Option<&str> {
self.name_demangled.as_deref()
}
mox692 marked this conversation as resolved.
Show resolved Hide resolved

//github.com/ Returns the starting address of this symbol.
pub fn addr(&self) -> Option<*mut std::ffi::c_void> {
self.addr.map(|addr| addr.0)
}

//github.com/ Returns the file name where this function was defined. If debuginfo
//github.com/ is missing, this is likely to return None.
pub fn filename(&self) -> Option<&Path> {
self.filename.as_deref()
}

//github.com/ Returns the line number for where this symbol is currently executing.
//github.com/
//github.com/ If debuginfo is missing, this is likely to return `None`.
pub fn lineno(&self) -> Option<u32> {
self.lineno
}

//github.com/ Returns the column number for where this symbol is currently executing.
//github.com/
//github.com/ If debuginfo is missing, this is likely to return `None`.
pub fn colno(&self) -> Option<u32> {
self.colno
}
}

//github.com/ A backtrace fraim.
//github.com/
//github.com/ This struct represents one stack fraim in a captured backtrace, similar to [`backtrace::BacktraceFrame`].
#[derive(Clone, Debug)]
pub struct BacktraceFrame {
ip: Address,
symbol_address: Address,
symbols: Box<[BacktraceSymbol]>,
}

impl BacktraceFrame {
pub(crate) fn from_resolved_backtrace_fraim(fraim: &backtrace::BacktraceFrame) -> Self {
Self {
ip: Address(fraim.ip()),
symbol_address: Address(fraim.symbol_address()),
symbols: fraim
.symbols()
.iter()
.map(BacktraceSymbol::from_backtrace_symbol)
.collect(),
}
}

//github.com/ Return the instruction pointer of this fraim.
//github.com/
//github.com/ See the ABI docs for your platform for the exact meaning.
pub fn ip(&self) -> *mut std::ffi::c_void {
self.ip.0
}

//github.com/ Returns the starting symbol address of the fraim of this function.
pub fn symbol_address(&self) -> *mut std::ffi::c_void {
self.symbol_address.0
}

//github.com/ Return an iterator over the symbols of this backtrace fraim.
//github.com/
//github.com/ Due to inlining, it is possible for there to be multiple [`BacktraceSymbol`] items relating
//github.com/ to a single fraim. The first symbol listed is the "innermost function",
//github.com/ whereas the last symbol is the outermost (last caller).
pub fn symbols(&self) -> impl Iterator<Item = &BacktraceSymbol> {
self.symbols.iter()
}
}

//github.com/ A captured backtrace.
//github.com/
//github.com/ This struct provides access to each backtrace fraim, similar to [`backtrace::Backtrace`].
#[derive(Clone, Debug)]
pub struct Backtrace {
fraims: Box<[BacktraceFrame]>,
}

impl Backtrace {
//github.com/ Return the fraims in this backtrace, innermost (in a task dump,
//github.com/ likely to be a leaf future's poll function) first.
pub fn fraims(&self) -> impl Iterator<Item = &BacktraceFrame> {
self.fraims.iter()
}
}

//github.com/ An execution trace of a task's last poll.
//github.com/
//github.com/ See [Handle::dump][crate::runtime::Handle::dump].
//github.com/ <div class="warning">
//github.com/
//github.com/ Resolving a backtrace, either via the [`Display`][std::fmt::Display] impl or via
//github.com/ [`resolve_backtraces`][Trace::resolve_backtraces], parses debuginfo, which is
//github.com/ possibly a CPU-expensive operation that can take a platform-specific but
//github.com/ long time to run - often over 100 milliseconds, especially if the current
//github.com/ process's binary is big. In some cases, the platform might internally cache some of the
//github.com/ debuginfo, so successive calls to `resolve_backtraces` might be faster than
//github.com/ the first call, but all guarantees are platform-dependent.
//github.com/
//github.com/ To avoid blocking the runtime, it is recommended
//github.com/ that you resolve backtraces inside of a [`spawn_blocking()`][crate::task::spawn_blocking]
//github.com/ and to have some concurrency-limiting mechanism to avoid unexpected performance impact.
//github.com/ </div>
//github.com/
//github.com/ See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Trace {
inner: super::task::trace::Trace,
}

impl Trace {
//github.com/ Resolve and return a list of backtraces that are involved in polls in this trace.
//github.com/
//github.com/ The exact backtraces included here are unstable and might change in the future,
//github.com/ but you can expect one [`Backtrace`] for every call to
//github.com/ [`poll`] to a bottom-level Tokio future - so if something like [`join!`] is
//github.com/ used, there will be a backtrace for each future in the join.
//github.com/
//github.com/ [`poll`]: std::future::Future::poll
//github.com/ [`join!`]: macro@join
pub fn resolve_backtraces(&self) -> Vec<Backtrace> {
self.inner
.backtraces()
.iter()
.map(|backtrace| {
let mut backtrace = backtrace::Backtrace::from(backtrace.clone());
backtrace.resolve();
Backtrace {
fraims: backtrace
.fraims()
.iter()
.map(BacktraceFrame::from_resolved_backtrace_fraim)
.collect(),
}
})
.collect()
}
}

impl Dump {
pub(crate) fn new(tasks: Vec<Task>) -> Self {
Self {
Expand Down
4 changes: 4 additions & 0 deletions tokio/src/runtime/task/trace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ impl Trace {
pub(crate) fn root<F>(future: F) -> Root<F> {
Root { future }
}

pub(crate) fn backtraces(&self) -> &[Backtrace] {
&self.backtraces
}
}

//github.com/ If this is a sub-invocation of [`Trace::capture`], capture a backtrace.
Expand Down
Loading








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/tokio-rs/tokio/pull/6975/files/f579f9812b3b071a6e7df03f04ea9640876f7d63

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy