@@ -89,12 +89,11 @@ mod tests;
89
89
// a backtrace or actually symbolizing it.
90
90
91
91
use crate :: backtrace_rs:: { self , BytesOrWideString } ;
92
- use crate :: cell:: UnsafeCell ;
93
92
use crate :: env;
94
93
use crate :: ffi:: c_void;
95
94
use crate :: fmt;
96
95
use crate :: sync:: atomic:: { AtomicUsize , Ordering :: Relaxed } ;
97
- use crate :: sync:: Once ;
96
+ use crate :: sync:: LazyLock ;
98
97
use crate :: sys_common:: backtrace:: { lock, output_filename} ;
99
98
use crate :: vec:: Vec ;
100
99
@@ -133,12 +132,11 @@ pub enum BacktraceStatus {
133
132
enum Inner {
134
133
Unsupported ,
135
134
Disabled ,
136
- Captured ( LazilyResolvedCapture ) ,
135
+ Captured ( LazyLock < Capture , LazyResolve > ) ,
137
136
}
138
137
139
138
struct Capture {
140
139
actual_start : usize ,
141
- resolved : bool ,
142
140
frames : Vec < BacktraceFrame > ,
143
141
}
144
142
@@ -179,7 +177,7 @@ impl fmt::Debug for Backtrace {
179
177
let capture = match & self . inner {
180
178
Inner :: Unsupported => return fmt. write_str ( "<unsupported>" ) ,
181
179
Inner :: Disabled => return fmt. write_str ( "<disabled>" ) ,
182
- Inner :: Captured ( c) => c . force ( ) ,
180
+ Inner :: Captured ( c) => & * * c ,
183
181
} ;
184
182
185
183
let frames = & capture. frames [ capture. actual_start ..] ;
@@ -347,11 +345,10 @@ impl Backtrace {
347
345
let inner = if frames. is_empty ( ) {
348
346
Inner :: Unsupported
349
347
} else {
350
- Inner :: Captured ( LazilyResolvedCapture :: new ( Capture {
348
+ Inner :: Captured ( LazyLock :: new ( lazy_resolve ( Capture {
351
349
actual_start : actual_start. unwrap_or ( 0 ) ,
352
350
frames,
353
- resolved : false ,
354
- } ) )
351
+ } ) ) )
355
352
} ;
356
353
357
354
Backtrace { inner }
@@ -376,7 +373,7 @@ impl<'a> Backtrace {
376
373
#[ must_use]
377
374
#[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
378
375
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 { & [ ] }
380
377
}
381
378
}
382
379
@@ -386,7 +383,7 @@ impl fmt::Display for Backtrace {
386
383
let capture = match & self . inner {
387
384
Inner :: Unsupported => return fmt. write_str ( "unsupported backtrace" ) ,
388
385
Inner :: Disabled => return fmt. write_str ( "disabled backtrace" ) ,
389
- Inner :: Captured ( c) => c . force ( ) ,
386
+ Inner :: Captured ( c) => & * * c ,
390
387
} ;
391
388
392
389
let full = fmt. alternate ( ) ;
@@ -430,46 +427,15 @@ impl fmt::Display for Backtrace {
430
427
}
431
428
}
432
429
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 ;
467
431
432
+ fn lazy_resolve ( mut capture : Capture ) -> LazyResolve {
433
+ move || {
468
434
// Use the global backtrace lock to synchronize this as it's a
469
435
// requirement of the `backtrace` crate, and then actually resolve
470
436
// everything.
471
437
let _lock = lock ( ) ;
472
- for frame in self . frames . iter_mut ( ) {
438
+ for frame in capture . frames . iter_mut ( ) {
473
439
let symbols = & mut frame. symbols ;
474
440
let frame = match & frame. frame {
475
441
RawFrame :: Actual ( frame) => frame,
@@ -490,6 +456,8 @@ impl Capture {
490
456
} ) ;
491
457
}
492
458
}
459
+
460
+ capture
493
461
}
494
462
}
495
463
0 commit comments