Skip to content

Commit

Permalink
Use old-style access to thread-local cells, to allow builds on pinned
Browse files Browse the repository at this point in the history
  • Loading branch information
target-san committed Dec 12, 2024
1 parent 9211183 commit d6b3009
Showing 1 changed file with 16 additions and 22 deletions.
38 changes: 16 additions & 22 deletions proptest/src/test_runner/scoped_panic_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,31 @@ thread_local! {
}

static INIT_ONCE: Once = Once::new();
/// Default panic hook, the one which was present before installing scoped one
///
/// NB: no need for external sync, value is mutated only once, when init is performed
static mut DEFAULT_HOOK: Option<Box<dyn Fn(&PanicInfo<'_>) + Send + Sync>> =
None;
/// Replaces currently installed panic hook with `scoped_hook_dispatcher` once,
/// in a thread-safe manner
fn init() {
INIT_ONCE.call_once(|| {
let old_handler = take_hook();
set_hook(Box::new(scoped_hook_dispatcher));
unsafe {
DEFAULT_HOOK = Some(old_handler);
}
set_hook(Box::new(move |panic_info| {
if !scoped_hook_dispatcher(panic_info) {
old_handler(panic_info)
}
}));
});
}
/// Panic hook which delegates execution to scoped hook,
/// if one installed, or to default hook
fn scoped_hook_dispatcher(info: &PanicInfo<'_>) {
let handler = SCOPED_HOOK_PTR.get();
if !handler.is_null() {
// It's assumed that if container's ptr is not null, ptr to `FnMut` is non-null too.
// Correctness **must** be ensured by hook switch code in `with_hook`
let hook = unsafe { &mut *(*handler).0 };
(hook)(info);
return;
fn scoped_hook_dispatcher(info: &PanicInfo<'_>) -> bool {
let handler = SCOPED_HOOK_PTR.with(Cell::get);
if handler.is_null() {
return false;
}
// It's assumed that if container's ptr is not null, ptr to `FnMut` is non-null too.
// Correctness **must** be ensured by hook switch code in `with_hook`
let hook = unsafe { &mut *(*handler).0 };
(hook)(info);

if let Some(hook) = unsafe { DEFAULT_HOOK.as_ref() } {
(hook)(info);
}
true
}
/// Executes stored closure when dropped
struct Finally<F: FnOnce()>(Option<F>);
Expand Down Expand Up @@ -105,10 +99,10 @@ pub fn with_hook<R>(
// `mem::transmute` is needed due to borrow checker restrictions to erase all lifetimes
mem::transmute(&mut panic_hook as *mut dyn FnMut(&PanicInfo<'_>))
},);
let old_tuple = SCOPED_HOOK_PTR.replace(&guard_tuple);
let old_tuple = SCOPED_HOOK_PTR.with(|c| c.replace(&guard_tuple));
// Old scoped hook **must** be restored before leaving function scope to keep it sound
let _undo = Finally::new(|| {
SCOPED_HOOK_PTR.set(old_tuple);
SCOPED_HOOK_PTR.with(|c| c.set(old_tuple));
});
body()
}

0 comments on commit d6b3009

Please sign in to comment.