@@ -89,12 +89,11 @@ mod tests;
8989// a backtrace or actually symbolizing it.
9090
9191use crate :: backtrace_rs:: { self , BytesOrWideString } ;
92- use crate :: cell:: UnsafeCell ;
9392use crate :: env;
9493use crate :: ffi:: c_void;
9594use crate :: fmt;
9695use crate :: sync:: atomic:: { AtomicUsize , Ordering :: Relaxed } ;
97- use crate :: sync:: Once ;
96+ use crate :: sync:: LazyLock ;
9897use crate :: sys_common:: backtrace:: { lock, output_filename} ;
9998use crate :: vec:: Vec ;
10099
@@ -133,20 +132,14 @@ pub enum BacktraceStatus {
133132enum Inner {
134133 Unsupported ,
135134 Disabled ,
136- Captured ( LazilyResolvedCapture ) ,
135+ Captured ( LazyLock < Capture , LazyResolve > ) ,
137136}
138137
139138struct Capture {
140139 actual_start : usize ,
141- resolved : bool ,
142140 frames : Vec < BacktraceFrame > ,
143141}
144142
145- fn _assert_send_sync ( ) {
146- fn _assert < T : Send + Sync > ( ) { }
147- _assert :: < Backtrace > ( ) ;
148- }
149-
150143/// A single frame of a backtrace.
151144#[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
152145pub struct BacktraceFrame {
@@ -179,7 +172,7 @@ impl fmt::Debug for Backtrace {
179172 let capture = match & self . inner {
180173 Inner :: Unsupported => return fmt. write_str ( "<unsupported>" ) ,
181174 Inner :: Disabled => return fmt. write_str ( "<disabled>" ) ,
182- Inner :: Captured ( c) => c . force ( ) ,
175+ Inner :: Captured ( c) => & * * c ,
183176 } ;
184177
185178 let frames = & capture. frames [ capture. actual_start ..] ;
@@ -347,11 +340,10 @@ impl Backtrace {
347340 let inner = if frames. is_empty ( ) {
348341 Inner :: Unsupported
349342 } else {
350- Inner :: Captured ( LazilyResolvedCapture :: new ( Capture {
343+ Inner :: Captured ( LazyLock :: new ( lazy_resolve ( Capture {
351344 actual_start : actual_start. unwrap_or ( 0 ) ,
352345 frames,
353- resolved : false ,
354- } ) )
346+ } ) ) )
355347 } ;
356348
357349 Backtrace { inner }
@@ -376,7 +368,7 @@ impl<'a> Backtrace {
376368 #[ must_use]
377369 #[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
378370 pub fn frames ( & ' a self ) -> & ' a [ BacktraceFrame ] {
379- if let Inner :: Captured ( c) = & self . inner { & c. force ( ) . frames } else { & [ ] }
371+ if let Inner :: Captured ( c) = & self . inner { & c. frames } else { & [ ] }
380372 }
381373}
382374
@@ -386,7 +378,7 @@ impl fmt::Display for Backtrace {
386378 let capture = match & self . inner {
387379 Inner :: Unsupported => return fmt. write_str ( "unsupported backtrace" ) ,
388380 Inner :: Disabled => return fmt. write_str ( "disabled backtrace" ) ,
389- Inner :: Captured ( c) => c . force ( ) ,
381+ Inner :: Captured ( c) => & * * c ,
390382 } ;
391383
392384 let full = fmt. alternate ( ) ;
@@ -430,46 +422,15 @@ impl fmt::Display for Backtrace {
430422 }
431423}
432424
433- struct LazilyResolvedCapture {
434- sync : Once ,
435- capture : UnsafeCell < Capture > ,
436- }
437-
438- impl LazilyResolvedCapture {
439- fn new ( capture : Capture ) -> Self {
440- LazilyResolvedCapture { sync : Once :: new ( ) , capture : UnsafeCell :: new ( capture) }
441- }
442-
443- fn force ( & self ) -> & Capture {
444- self . sync . call_once ( || {
445- // SAFETY: This exclusive reference can't overlap with any others
446- // `Once` guarantees callers will block until this closure returns
447- // `Once` also guarantees only a single caller will enter this closure
448- unsafe { & mut * self . capture . get ( ) } . resolve ( ) ;
449- } ) ;
450-
451- // SAFETY: This shared reference can't overlap with the exclusive reference above
452- unsafe { & * self . capture . get ( ) }
453- }
454- }
455-
456- // SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
457- // So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
458- unsafe impl Sync for LazilyResolvedCapture where Capture : Sync { }
459-
460- impl Capture {
461- fn resolve ( & mut self ) {
462- // If we're already resolved, nothing to do!
463- if self . resolved {
464- return ;
465- }
466- self . resolved = true ;
425+ type LazyResolve = impl FnOnce ( ) -> Capture ;
467426
427+ fn lazy_resolve ( mut capture : Capture ) -> LazyResolve {
428+ move || {
468429 // Use the global backtrace lock to synchronize this as it's a
469430 // requirement of the `backtrace` crate, and then actually resolve
470431 // everything.
471432 let _lock = lock ( ) ;
472- for frame in self . frames . iter_mut ( ) {
433+ for frame in capture . frames . iter_mut ( ) {
473434 let symbols = & mut frame. symbols ;
474435 let frame = match & frame. frame {
475436 RawFrame :: Actual ( frame) => frame,
@@ -490,6 +451,8 @@ impl Capture {
490451 } ) ;
491452 }
492453 }
454+
455+ capture
493456 }
494457}
495458
0 commit comments