@@ -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,20 +132,14 @@ 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
145
- fn _assert_send_sync ( ) {
146
- fn _assert < T : Send + Sync > ( ) { }
147
- _assert :: < Backtrace > ( ) ;
148
- }
149
-
150
143
/// A single frame of a backtrace.
151
144
#[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
152
145
pub struct BacktraceFrame {
@@ -179,7 +172,7 @@ impl fmt::Debug for Backtrace {
179
172
let capture = match & self . inner {
180
173
Inner :: Unsupported => return fmt. write_str ( "<unsupported>" ) ,
181
174
Inner :: Disabled => return fmt. write_str ( "<disabled>" ) ,
182
- Inner :: Captured ( c) => c . force ( ) ,
175
+ Inner :: Captured ( c) => & * * c ,
183
176
} ;
184
177
185
178
let frames = & capture. frames [ capture. actual_start ..] ;
@@ -347,11 +340,10 @@ impl Backtrace {
347
340
let inner = if frames. is_empty ( ) {
348
341
Inner :: Unsupported
349
342
} else {
350
- Inner :: Captured ( LazilyResolvedCapture :: new ( Capture {
343
+ Inner :: Captured ( LazyLock :: new ( lazy_resolve ( Capture {
351
344
actual_start : actual_start. unwrap_or ( 0 ) ,
352
345
frames,
353
- resolved : false ,
354
- } ) )
346
+ } ) ) )
355
347
} ;
356
348
357
349
Backtrace { inner }
@@ -376,7 +368,7 @@ impl<'a> Backtrace {
376
368
#[ must_use]
377
369
#[ unstable( feature = "backtrace_frames" , issue = "79676" ) ]
378
370
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 { & [ ] }
380
372
}
381
373
}
382
374
@@ -386,7 +378,7 @@ impl fmt::Display for Backtrace {
386
378
let capture = match & self . inner {
387
379
Inner :: Unsupported => return fmt. write_str ( "unsupported backtrace" ) ,
388
380
Inner :: Disabled => return fmt. write_str ( "disabled backtrace" ) ,
389
- Inner :: Captured ( c) => c . force ( ) ,
381
+ Inner :: Captured ( c) => & * * c ,
390
382
} ;
391
383
392
384
let full = fmt. alternate ( ) ;
@@ -430,46 +422,15 @@ impl fmt::Display for Backtrace {
430
422
}
431
423
}
432
424
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 ;
467
426
427
+ fn lazy_resolve ( mut capture : Capture ) -> LazyResolve {
428
+ move || {
468
429
// Use the global backtrace lock to synchronize this as it's a
469
430
// requirement of the `backtrace` crate, and then actually resolve
470
431
// everything.
471
432
let _lock = lock ( ) ;
472
- for frame in self . frames . iter_mut ( ) {
433
+ for frame in capture . frames . iter_mut ( ) {
473
434
let symbols = & mut frame. symbols ;
474
435
let frame = match & frame. frame {
475
436
RawFrame :: Actual ( frame) => frame,
@@ -490,6 +451,8 @@ impl Capture {
490
451
} ) ;
491
452
}
492
453
}
454
+
455
+ capture
493
456
}
494
457
}
495
458
0 commit comments