Skip to content

Commit befadb7

Browse files
committed
Give WORKS initialization its own function
1 parent fad56f7 commit befadb7

File tree

1 file changed

+40
-39
lines changed

1 file changed

+40
-39
lines changed

src/detection.rs

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)