@@ -12,47 +12,48 @@ pub(crate) fn inside_proc_macro() -> bool {
1212 _ => { }
1313 }
1414
15- // Swap in a null panic hook to avoid printing "thread panicked" to stderr,
16- // then use catch_unwind to determine whether the compiler's proc_macro is
17- // working. When proc-macro2 is used from outside of a procedural macro all
18- // of the proc_macro crate's APIs currently panic.
19- //
20- // The Once is to prevent the possibility of this ordering:
21- //
22- // thread 1 calls take_hook, gets the user's original hook
23- // thread 1 calls set_hook with the null hook
24- // thread 2 calls take_hook, thinks null hook is the original hook
25- // thread 2 calls set_hook with the null hook
26- // thread 1 calls set_hook with the actual original hook
27- // thread 2 calls set_hook with what it thinks is the original hook
28- //
29- // in which the user's hook has been lost.
30- //
31- // There is still a race condition where a panic in a different thread can
32- // happen during the interval that the user's original panic hook is
33- // unregistered such that their hook is incorrectly not called. This is
34- // sufficiently unlikely and less bad than printing panic messages to stderr
35- // on correct use of this crate. Maybe there is a libstd feature request
36- // here. For now, if a user needs to guarantee that this failure mode does
37- // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
38- // the main thread before launching any other threads.
39- INIT . call_once ( || {
40- type PanicHook = dyn Fn ( & PanicInfo ) + Sync + Send + ' static ;
15+ INIT . call_once ( initialize) ;
16+ inside_proc_macro ( )
17+ }
4118
42- let null_hook: Box < PanicHook > = Box :: new ( |_panic_info| { /* ignore */ } ) ;
43- let sanity_check = & * null_hook as * const PanicHook ;
44- let original_hook = panic:: take_hook ( ) ;
45- panic:: set_hook ( null_hook) ;
19+ // Swap in a null panic hook to avoid printing "thread panicked" to stderr,
20+ // then use catch_unwind to determine whether the compiler's proc_macro is
21+ // working. When proc-macro2 is used from outside of a procedural macro all
22+ // of the proc_macro crate's APIs currently panic.
23+ //
24+ // The Once is to prevent the possibility of this ordering:
25+ //
26+ // thread 1 calls take_hook, gets the user's original hook
27+ // thread 1 calls set_hook with the null hook
28+ // thread 2 calls take_hook, thinks null hook is the original hook
29+ // thread 2 calls set_hook with the null hook
30+ // thread 1 calls set_hook with the actual original hook
31+ // thread 2 calls set_hook with what it thinks is the original hook
32+ //
33+ // in which the user's hook has been lost.
34+ //
35+ // There is still a race condition where a panic in a different thread can
36+ // happen during the interval that the user's original panic hook is
37+ // unregistered such that their hook is incorrectly not called. This is
38+ // sufficiently unlikely and less bad than printing panic messages to stderr
39+ // on correct use of this crate. Maybe there is a libstd feature request
40+ // here. For now, if a user needs to guarantee that this failure mode does
41+ // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
42+ // the main thread before launching any other threads.
43+ fn initialize ( ) {
44+ type PanicHook = dyn Fn ( & PanicInfo ) + Sync + Send + ' static ;
4645
47- let works = panic:: catch_unwind ( proc_macro:: Span :: call_site) . is_ok ( ) ;
48- WORKS . store ( works as usize + 1 , Ordering :: SeqCst ) ;
46+ let null_hook: Box < PanicHook > = Box :: new ( |_panic_info| { /* ignore */ } ) ;
47+ let sanity_check = & * null_hook as * const PanicHook ;
48+ let original_hook = panic:: take_hook ( ) ;
49+ panic:: set_hook ( null_hook) ;
4950
50- let hopefully_null_hook = panic:: take_hook ( ) ;
51- panic:: set_hook ( original_hook) ;
52- if sanity_check != & * hopefully_null_hook {
53- panic ! ( "observed race condition in proc_macro2::inside_proc_macro" ) ;
54- }
55- } ) ;
51+ let works = panic:: catch_unwind ( proc_macro:: Span :: call_site) . is_ok ( ) ;
52+ WORKS . store ( works as usize + 1 , Ordering :: SeqCst ) ;
5653
57- inside_proc_macro ( )
54+ let hopefully_null_hook = panic:: take_hook ( ) ;
55+ panic:: set_hook ( original_hook) ;
56+ if sanity_check != & * hopefully_null_hook {
57+ panic ! ( "observed race condition in proc_macro2::inside_proc_macro" ) ;
58+ }
5859}
0 commit comments