@@ -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,12 +132,11 @@ 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
@@ -179,7 +177,7 @@ impl fmt::Debug for Backtrace {
179177 let capture = match & self . inner {
180178 Inner :: Unsupported => return fmt. write_str ( "<unsupported>" ) ,
181179 Inner :: Disabled => return fmt. write_str ( "<disabled>" ) ,
182- Inner :: Captured ( c) => c . force ( ) ,
180+ Inner :: Captured ( c) => & * * c ,
183181 } ;
184182
185183 let frames = & capture. frames [ capture. actual_start ..] ;
@@ -347,11 +345,10 @@ impl Backtrace {
347345 let inner = if frames. is_empty ( ) {
348346 Inner :: Unsupported
349347 } else {
350- Inner :: Captured ( LazilyResolvedCapture :: new ( Capture {
348+ Inner :: Captured ( LazyLock :: new ( lazy_resolve ( Capture {
351349 actual_start : actual_start. unwrap_or ( 0 ) ,
352350 frames,
353- resolved : false ,
354- } ) )
351+ } ) ) )
355352 } ;
356353
357354 Backtrace { inner }
@@ -376,7 +373,7 @@ impl<'a> Backtrace {
376373 #[ must_use]
377374 #[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
378375 pub fn frames ( & ' a self ) -> & ' a [ BacktraceFrame ] {
379- if let Inner :: Captured ( c) = & self . inner { & c. force ( ) . frames } else { & [ ] }
376+ if let Inner :: Captured ( c) = & self . inner { & c. frames } else { & [ ] }
380377 }
381378}
382379
@@ -386,7 +383,7 @@ impl fmt::Display for Backtrace {
386383 let capture = match & self . inner {
387384 Inner :: Unsupported => return fmt. write_str ( "unsupported backtrace" ) ,
388385 Inner :: Disabled => return fmt. write_str ( "disabled backtrace" ) ,
389- Inner :: Captured ( c) => c . force ( ) ,
386+ Inner :: Captured ( c) => & * * c ,
390387 } ;
391388
392389 let full = fmt. alternate ( ) ;
@@ -430,46 +427,15 @@ impl fmt::Display for Backtrace {
430427 }
431428}
432429
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 ;
430+ type LazyResolve = impl ( FnOnce ( ) -> Capture ) + Send + Sync ;
467431
432+ fn lazy_resolve ( mut capture : Capture ) -> LazyResolve {
433+ move || {
468434 // Use the global backtrace lock to synchronize this as it's a
469435 // requirement of the `backtrace` crate, and then actually resolve
470436 // everything.
471437 let _lock = lock ( ) ;
472- for frame in self . frames . iter_mut ( ) {
438+ for frame in capture . frames . iter_mut ( ) {
473439 let symbols = & mut frame. symbols ;
474440 let frame = match & frame. frame {
475441 RawFrame :: Actual ( frame) => frame,
@@ -490,6 +456,8 @@ impl Capture {
490456 } ) ;
491457 }
492458 }
459+
460+ capture
493461 }
494462}
495463
0 commit comments