summaryrefslogtreecommitdiffstats
path: root/library/std/src/backtrace.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /library/std/src/backtrace.rs
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/backtrace.rs')
-rw-r--r--library/std/src/backtrace.rs59
1 files changed, 14 insertions, 45 deletions
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7543ffadd..e7110aebd 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -89,12 +89,12 @@ mod tests;
// a backtrace or actually symbolizing it.
use crate::backtrace_rs::{self, BytesOrWideString};
-use crate::cell::UnsafeCell;
use crate::env;
use crate::ffi::c_void;
use crate::fmt;
+use crate::panic::UnwindSafe;
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-use crate::sync::Once;
+use crate::sync::LazyLock;
use crate::sys_common::backtrace::{lock, output_filename};
use crate::vec::Vec;
@@ -133,12 +133,11 @@ pub enum BacktraceStatus {
enum Inner {
Unsupported,
Disabled,
- Captured(LazilyResolvedCapture),
+ Captured(LazyLock<Capture, LazyResolve>),
}
struct Capture {
actual_start: usize,
- resolved: bool,
frames: Vec<BacktraceFrame>,
}
@@ -179,7 +178,7 @@ impl fmt::Debug for Backtrace {
let capture = match &self.inner {
Inner::Unsupported => return fmt.write_str("<unsupported>"),
Inner::Disabled => return fmt.write_str("<disabled>"),
- Inner::Captured(c) => c.force(),
+ Inner::Captured(c) => &**c,
};
let frames = &capture.frames[capture.actual_start..];
@@ -347,11 +346,10 @@ impl Backtrace {
let inner = if frames.is_empty() {
Inner::Unsupported
} else {
- Inner::Captured(LazilyResolvedCapture::new(Capture {
+ Inner::Captured(LazyLock::new(lazy_resolve(Capture {
actual_start: actual_start.unwrap_or(0),
frames,
- resolved: false,
- }))
+ })))
};
Backtrace { inner }
@@ -376,7 +374,7 @@ impl<'a> Backtrace {
#[must_use]
#[unstable(feature = "backtrace_frames", issue = "79676")]
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
- if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
+ if let Inner::Captured(c) = &self.inner { &c.frames } else { &[] }
}
}
@@ -386,7 +384,7 @@ impl fmt::Display for Backtrace {
let capture = match &self.inner {
Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
Inner::Disabled => return fmt.write_str("disabled backtrace"),
- Inner::Captured(c) => c.force(),
+ Inner::Captured(c) => &**c,
};
let full = fmt.alternate();
@@ -430,46 +428,15 @@ impl fmt::Display for Backtrace {
}
}
-struct LazilyResolvedCapture {
- sync: Once,
- capture: UnsafeCell<Capture>,
-}
-
-impl LazilyResolvedCapture {
- fn new(capture: Capture) -> Self {
- LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
- }
-
- fn force(&self) -> &Capture {
- self.sync.call_once(|| {
- // SAFETY: This exclusive reference can't overlap with any others
- // `Once` guarantees callers will block until this closure returns
- // `Once` also guarantees only a single caller will enter this closure
- unsafe { &mut *self.capture.get() }.resolve();
- });
-
- // SAFETY: This shared reference can't overlap with the exclusive reference above
- unsafe { &*self.capture.get() }
- }
-}
-
-// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
-// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
-unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
-
-impl Capture {
- fn resolve(&mut self) {
- // If we're already resolved, nothing to do!
- if self.resolved {
- return;
- }
- self.resolved = true;
+type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
+fn lazy_resolve(mut capture: Capture) -> LazyResolve {
+ move || {
// Use the global backtrace lock to synchronize this as it's a
// requirement of the `backtrace` crate, and then actually resolve
// everything.
let _lock = lock();
- for frame in self.frames.iter_mut() {
+ for frame in capture.frames.iter_mut() {
let symbols = &mut frame.symbols;
let frame = match &frame.frame {
RawFrame::Actual(frame) => frame,
@@ -490,6 +457,8 @@ impl Capture {
});
}
}
+
+ capture
}
}