Skip to content

Commit 948bef6

Browse files
committed
Revert "std: use LazyLock to lazily resolve backtraces"
This reverts commit 6776af5.
1 parent 8df48d6 commit 948bef6

File tree

5 files changed

+54
-35
lines changed

5 files changed

+54
-35
lines changed

library/std/src/backtrace.rs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ mod tests;
8989
// a backtrace or actually symbolizing it.
9090

9191
use crate::backtrace_rs::{self, BytesOrWideString};
92+
use crate::cell::UnsafeCell;
9293
use crate::env;
9394
use crate::ffi::c_void;
9495
use crate::fmt;
9596
use crate::panic::UnwindSafe;
9697
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
97-
use crate::sync::LazyLock;
98+
use crate::sync::Once;
9899
use crate::sys_common::backtrace::{lock, output_filename};
99100
use crate::vec::Vec;
100101

@@ -133,14 +134,20 @@ pub enum BacktraceStatus {
133134
enum Inner {
134135
Unsupported,
135136
Disabled,
136-
Captured(LazyLock<Capture, LazyResolve>),
137+
Captured(LazilyResolvedCapture),
137138
}
138139

139140
struct Capture {
140141
actual_start: usize,
142+
resolved: bool,
141143
frames: Vec<BacktraceFrame>,
142144
}
143145

146+
fn _assert_send_sync() {
147+
fn _assert<T: Send + Sync>() {}
148+
_assert::<Backtrace>();
149+
}
150+
144151
/// A single frame of a backtrace.
145152
#[unstable(feature = "backtrace_frames", issue = "79676")]
146153
pub struct BacktraceFrame {
@@ -173,7 +180,7 @@ impl fmt::Debug for Backtrace {
173180
let capture = match &self.inner {
174181
Inner::Unsupported => return fmt.write_str("<unsupported>"),
175182
Inner::Disabled => return fmt.write_str("<disabled>"),
176-
Inner::Captured(c) => &**c,
183+
Inner::Captured(c) => c.force(),
177184
};
178185

179186
let frames = &capture.frames[capture.actual_start..];
@@ -341,10 +348,11 @@ impl Backtrace {
341348
let inner = if frames.is_empty() {
342349
Inner::Unsupported
343350
} else {
344-
Inner::Captured(LazyLock::new(lazy_resolve(Capture {
351+
Inner::Captured(LazilyResolvedCapture::new(Capture {
345352
actual_start: actual_start.unwrap_or(0),
346353
frames,
347-
})))
354+
resolved: false,
355+
}))
348356
};
349357

350358
Backtrace { inner }
@@ -369,7 +377,7 @@ impl<'a> Backtrace {
369377
#[must_use]
370378
#[unstable(feature = "backtrace_frames", issue = "79676")]
371379
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
372-
if let Inner::Captured(c) = &self.inner { &c.frames } else { &[] }
380+
if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
373381
}
374382
}
375383

@@ -379,7 +387,7 @@ impl fmt::Display for Backtrace {
379387
let capture = match &self.inner {
380388
Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
381389
Inner::Disabled => return fmt.write_str("disabled backtrace"),
382-
Inner::Captured(c) => &**c,
390+
Inner::Captured(c) => c.force(),
383391
};
384392

385393
let full = fmt.alternate();
@@ -423,15 +431,46 @@ impl fmt::Display for Backtrace {
423431
}
424432
}
425433

426-
type LazyResolve = impl FnOnce() -> Capture + UnwindSafe;
434+
struct LazilyResolvedCapture {
435+
sync: Once,
436+
capture: UnsafeCell<Capture>,
437+
}
438+
439+
impl LazilyResolvedCapture {
440+
fn new(capture: Capture) -> Self {
441+
LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
442+
}
443+
444+
fn force(&self) -> &Capture {
445+
self.sync.call_once(|| {
446+
// SAFETY: This exclusive reference can't overlap with any others
447+
// `Once` guarantees callers will block until this closure returns
448+
// `Once` also guarantees only a single caller will enter this closure
449+
unsafe { &mut *self.capture.get() }.resolve();
450+
});
451+
452+
// SAFETY: This shared reference can't overlap with the exclusive reference above
453+
unsafe { &*self.capture.get() }
454+
}
455+
}
456+
457+
// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
458+
// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
459+
unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
460+
461+
impl Capture {
462+
fn resolve(&mut self) {
463+
// If we're already resolved, nothing to do!
464+
if self.resolved {
465+
return;
466+
}
467+
self.resolved = true;
427468

428-
fn lazy_resolve(mut capture: Capture) -> LazyResolve {
429-
move || {
430469
// Use the global backtrace lock to synchronize this as it's a
431470
// requirement of the `backtrace` crate, and then actually resolve
432471
// everything.
433472
let _lock = lock();
434-
for frame in capture.frames.iter_mut() {
473+
for frame in self.frames.iter_mut() {
435474
let symbols = &mut frame.symbols;
436475
let frame = match &frame.frame {
437476
RawFrame::Actual(frame) => frame,
@@ -452,8 +491,6 @@ fn lazy_resolve(mut capture: Capture) -> LazyResolve {
452491
});
453492
}
454493
}
455-
456-
capture
457494
}
458495
}
459496

library/std/src/backtrace/tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ fn generate_fake_frames() -> Vec<BacktraceFrame> {
4444
#[test]
4545
fn test_debug() {
4646
let backtrace = Backtrace {
47-
inner: Inner::Captured(LazyLock::preinit(Capture {
47+
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
4848
actual_start: 1,
49+
resolved: true,
4950
frames: generate_fake_frames(),
5051
})),
5152
};
@@ -66,8 +67,9 @@ fn test_debug() {
6667
#[test]
6768
fn test_frames() {
6869
let backtrace = Backtrace {
69-
inner: Inner::Captured(LazyLock::preinit(Capture {
70+
inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
7071
actual_start: 1,
72+
resolved: true,
7173
frames: generate_fake_frames(),
7274
})),
7375
};

library/std/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@
273273
#![feature(staged_api)]
274274
#![feature(thread_local)]
275275
#![feature(try_blocks)]
276-
#![feature(type_alias_impl_trait)]
277276
#![feature(utf8_chunks)]
278277
// tidy-alphabetical-end
279278
//

library/std/src/sync/lazy_lock.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
8989
LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
9090
}
9191

92-
/// Creates a new lazy value that is already initialized.
93-
#[inline]
94-
#[cfg(test)]
95-
pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
96-
let once = Once::new();
97-
once.call_once(|| {});
98-
LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
99-
}
100-
10192
/// Consumes this `LazyLock` returning the stored value.
10293
///
10394
/// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.

library/std/tests/backtrace.rs

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)