3
3
//! See [Handle::dump][crate::runtime::Handle::dump].
4
4
5
5
use crate :: task:: Id ;
6
- use std:: fmt;
6
+ use std:: { fmt, path :: Path } ;
7
7
8
8
/// A snapshot of a runtime's state.
9
9
///
@@ -30,14 +30,158 @@ pub struct Task {
30
30
trace : Trace ,
31
31
}
32
32
33
+ /// A backtrace symbol. This is similar to [backtrace::BacktraceSymbol],
34
+ /// but is a separate struct to avoid public dependency issues.
35
+ ///
36
+ /// This struct is guaranteed to be pure data and operations involving
37
+ /// it will not call platform functions that take an unpredictable amount
38
+ /// of time to finish.
39
+ #[ derive( Clone , Debug ) ]
40
+ pub struct BacktraceSymbol {
41
+ name : Option < Vec < u8 > > ,
42
+ name_demangled : Option < String > ,
43
+ addr : Option < * mut std:: ffi:: c_void > ,
44
+ filename : Option < std:: path:: PathBuf > ,
45
+ lineno : Option < u32 > ,
46
+ colno : Option < u32 > ,
47
+ }
48
+
49
+ impl BacktraceSymbol {
50
+ pub ( crate ) fn from_backtrace_symbol ( sym : & backtrace:: BacktraceSymbol ) -> Self {
51
+ let name = sym. name ( ) ;
52
+ Self {
53
+ name : name. as_ref ( ) . map ( |name| name. as_bytes ( ) . into ( ) ) ,
54
+ name_demangled : name. map ( |name| format ! ( "{}" , name) ) ,
55
+ addr : sym. addr ( ) ,
56
+ filename : sym. filename ( ) . map ( From :: from) ,
57
+ lineno : sym. lineno ( ) ,
58
+ colno : sym. colno ( ) ,
59
+ }
60
+ }
61
+
62
+ /// Return the raw name of the symbol.
63
+ pub fn name_raw ( & self ) -> Option < & [ u8 ] > {
64
+ self . name . as_deref ( )
65
+ }
66
+
67
+ /// Return the demangled name of the symbol.
68
+ pub fn name_demangled ( & self ) -> Option < & str > {
69
+ self . name_demangled . as_deref ( )
70
+ }
71
+
72
+ /// Returns the starting address of this symbol.
73
+ pub fn addr ( & self ) -> Option < * mut std:: ffi:: c_void > {
74
+ self . addr
75
+ }
76
+
77
+ /// Returns the file name where this function was defined. If debuginfo
78
+ /// is missing, this is likely to return None.
79
+ pub fn filename ( & self ) -> Option < & Path > {
80
+ self . filename . as_deref ( )
81
+ }
82
+
83
+ /// Returns the line number for where this symbol is currently executing If debuginfo
84
+ /// is missing, this is likely to return None.
85
+ pub fn lineno ( & self ) -> Option < u32 > {
86
+ self . lineno
87
+ }
88
+
89
+ /// Returns the column number for where this symbol is currently executing If debuginfo
90
+ /// is missing, this is likely to return None.
91
+ pub fn colno ( & self ) -> Option < u32 > {
92
+ self . colno
93
+ }
94
+ }
95
+
96
+ /// A backtrace frame. This is similar to [backtrace::BacktraceFrame],
97
+ /// but is a separate struct to avoid public dependency issues.
98
+ ///
99
+ /// This struct is guaranteed to be pure data and operations involving
100
+ /// it will not call platform functions that take an unpredictable amount
101
+ /// of time to finish.
102
+ #[ derive( Clone , Debug ) ]
103
+ pub struct BacktraceFrame {
104
+ ip : * mut std:: ffi:: c_void ,
105
+ symbol_address : * mut std:: ffi:: c_void ,
106
+ symbols : Vec < BacktraceSymbol > ,
107
+ }
108
+
109
+ impl BacktraceFrame {
110
+ pub ( crate ) fn from_resolved_backtrace_frame ( frame : & backtrace:: BacktraceFrame ) -> Self {
111
+ Self {
112
+ ip : frame. ip ( ) ,
113
+ symbol_address : frame. symbol_address ( ) ,
114
+ symbols : frame
115
+ . symbols ( )
116
+ . iter ( )
117
+ . map ( BacktraceSymbol :: from_backtrace_symbol)
118
+ . collect ( ) ,
119
+ }
120
+ }
121
+
122
+ /// Return the instruction pointer of this frame.
123
+ ///
124
+ /// See the ABI docs for your platform for the exact meaning.
125
+ pub fn ip ( & self ) -> * mut std:: ffi:: c_void {
126
+ self . ip
127
+ }
128
+
129
+ /// Returns the starting symbol address of the frame of this function.
130
+ pub fn symbol_address ( & self ) -> * mut std:: ffi:: c_void {
131
+ self . symbol_address
132
+ }
133
+
134
+ /// Return an iterator over the symbols of this backtrace frame.
135
+ ///
136
+ /// Due to inlining, it is possible for there to be multiple [BacktraceSymbol] items relating
137
+ /// to a single frame. The first symbol listed is the "innermost function",
138
+ /// whereas the last symbol is the outermost (last caller).
139
+ pub fn symbols ( & self ) -> impl Iterator < Item = & BacktraceSymbol > {
140
+ self . symbols . iter ( )
141
+ }
142
+ }
143
+
33
144
/// An execution trace of a task's last poll.
34
145
///
146
+ /// <div class="warning">
147
+ /// Resolving a backtrace, either via the [`Display`][std::fmt::Display] impl or via
148
+ /// [`resolve_backtraces`][Trace::resolve_backtraces], parses debuginfo, which is
149
+ /// possibly a CPU-expensive operation that can take a platform-specific but
150
+ /// long time to run - often over 100 milliseconds, especially if the current
151
+ /// process's binary is big. In some cases, the platform might internally cache some of the
152
+ /// debuginfo, so successive calls to `resolve_backtraces` might be faster than
153
+ /// the first call, but all guarantees are platform-dependent.
154
+ ///
155
+ /// To avoid blocking the runtime, it is recommended
156
+ /// that you resolve backtraces inside of a [spawn_blocking()][crate::task::spawn_blocking]
157
+ /// and to have some concurrency-limiting mechanism to avoid unexpected performance impact.
158
+ /// </div>
159
+ ///
35
160
/// See [Handle::dump][crate::runtime::Handle::dump].
36
161
#[ derive( Debug ) ]
37
162
pub struct Trace {
38
163
inner : super :: task:: trace:: Trace ,
39
164
}
40
165
166
+ impl Trace {
167
+ /// Resolve and return a list of backtraces that are involved in polls in this task.
168
+ pub fn resolve_backtraces ( & self ) -> Vec < Vec < BacktraceFrame > > {
169
+ self . inner
170
+ . backtraces ( )
171
+ . iter ( )
172
+ . map ( |backtrace| {
173
+ let mut backtrace = backtrace:: Backtrace :: from ( backtrace. clone ( ) ) ;
174
+ backtrace. resolve ( ) ;
175
+ backtrace
176
+ . frames ( )
177
+ . iter ( )
178
+ . map ( BacktraceFrame :: from_resolved_backtrace_frame)
179
+ . collect ( )
180
+ } )
181
+ . collect ( )
182
+ }
183
+ }
184
+
41
185
impl Dump {
42
186
pub ( crate ) fn new ( tasks : Vec < Task > ) -> Self {
43
187
Self {
0 commit comments