-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Expose Frames Iterator for the Backtrace Type #78299
Changes from 23 commits
372ba21
9b8e4fc
e07b25d
277a2a4
b4e21e6
43f2774
7331efe
b43bcb6
6df53a1
37f4f13
747bb91
c5d5912
30c5494
4e6d2ef
e7df885
61b198f
b4175b1
b30f662
c624d22
de98734
da2e4a9
0199300
48e6a38
ff81eb1
43b9783
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,7 @@ use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; | |
use crate::sync::Mutex; | ||
use crate::sys_common::backtrace::{lock, output_filename}; | ||
use crate::vec::Vec; | ||
use crate::marker::PhantomData; | ||
|
||
/// A captured OS thread stack backtrace. | ||
/// | ||
|
@@ -146,23 +147,38 @@ fn _assert_send_sync() { | |
_assert::<Backtrace>(); | ||
} | ||
|
||
struct BacktraceFrame { | ||
/// A single frame of a backtrace. | ||
#[derive(Debug)] | ||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
pub struct BacktraceFrame { | ||
frame: RawFrame, | ||
symbols: Vec<BacktraceSymbol>, | ||
} | ||
|
||
/// An iterator over the frames of a backtrace, created | ||
/// by the [`frames`] method on [`Backtrace`]. | ||
#[derive(Debug)] | ||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
pub struct Frames<'a> { | ||
inner: Vec<BacktraceFrame>, | ||
_backtrace: PhantomData<&'a Backtrace> | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
enum RawFrame { | ||
Actual(backtrace_rs::Frame), | ||
#[cfg(test)] | ||
Fake, | ||
} | ||
|
||
#[derive(Clone)] | ||
struct BacktraceSymbol { | ||
name: Option<Vec<u8>>, | ||
filename: Option<BytesOrWide>, | ||
lineno: Option<u32>, | ||
} | ||
|
||
#[derive(Clone)] | ||
enum BytesOrWide { | ||
Bytes(Vec<u8>), | ||
Wide(Vec<u16>), | ||
|
@@ -348,6 +364,25 @@ impl Backtrace { | |
} | ||
} | ||
|
||
impl<'a> Backtrace { | ||
/// Returns an iterator over the backtrace frames. | ||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
pub fn frames(&self) -> Frames<'a> { | ||
if let Inner::Captured(captured) = &self.inner { | ||
let frames = &captured.lock().unwrap().frames; | ||
Frames { | ||
inner: frames.iter().map(|frame| frame.clone()).collect::<Vec<BacktraceFrame>>(), | ||
_backtrace: PhantomData | ||
} | ||
} else { | ||
Frames { | ||
inner: vec![], | ||
_backtrace: PhantomData | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl fmt::Display for Backtrace { | ||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
let mut capture = match &self.inner { | ||
|
@@ -443,3 +478,33 @@ impl RawFrame { | |
} | ||
} | ||
} | ||
|
||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
impl<'a> AsRef<[BacktraceFrame]> for Frames<'a> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be incompatible with lazy resolving of backtraces. Only an Iterator would be compatible. |
||
fn as_ref(&self) -> &[BacktraceFrame] { | ||
&self.inner | ||
} | ||
} | ||
|
||
|
||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
impl BacktraceFrame { | ||
// Private clone method so that we don't expose a | ||
// public BacktraceFrame.clone() by deriving Clone | ||
fn clone(&self) -> Self { | ||
BacktraceFrame { | ||
frame: self.frame.clone(), | ||
symbols: self.symbols.clone(), | ||
} | ||
} | ||
} | ||
|
||
#[unstable(feature = "backtrace_frames", issue = "79676")] | ||
impl<'a> Iterator for Frames<'a> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we'll want to avoid adding an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think in the future it should actually lazily resolve the frames as |
||
type Item = BacktraceFrame; | ||
|
||
fn next(&mut self) -> Option<BacktraceFrame> { | ||
self.inner.pop() | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So with this change, what's the way to access the type inside of the
SyncLazy
? Before with theMutex
we hadWhat would we need to change the
let frames
line into to access the underlyingframes
?