#[cfg(feature = "interrupt")]mod needs_feature { use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use signal_hook::consts::SIGTERM; #[test] fn multi_registration() -> gix_testtools::Result { static V1: AtomicUsize = AtomicUsize::new(0); static V2: AtomicBool = AtomicBool::new(false); // SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler. let reg1 = unsafe { gix::interrupt::init_handler(3, || { V1.fetch_add(1, Ordering::SeqCst); }) } .expect("succeeds"); assert!(!gix::interrupt::is_triggered()); assert_eq!(V1.load(Ordering::Relaxed), 0); // SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler. let reg2 = unsafe { gix::interrupt::init_handler(2, || V2.store(true, Ordering::SeqCst)) } .expect("multi-initialization is OK"); assert!(!V2.load(Ordering::Relaxed)); signal_hook::low_level::raise(SIGTERM).expect("signal can be raised"); assert!(gix::interrupt::is_triggered(), "this happens automatically"); assert_eq!(V1.load(Ordering::Relaxed), 1, "the first trigger is invoked"); assert!(!V2.load(Ordering::Relaxed), "the second trigger was ignored"); reg1.deregister()?; signal_hook::low_level::raise(SIGTERM).expect("signal can be raised"); assert_eq!(V1.load(Ordering::Relaxed), 2, "the first trigger is still invoked"); assert!(gix::interrupt::is_triggered(), "this happens automatically"); // now the registration is actually removed. reg2.with_reset(true).deregister()?; assert!( !gix::interrupt::is_triggered(), "the deregistration succeeded and this is an optional side-effect" ); // SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler. let reg1 = unsafe { gix::interrupt::init_handler(3, || { V1.fetch_add(1, Ordering::SeqCst); }) } .expect("succeeds"); assert_eq!(V1.load(Ordering::Relaxed), 2, "nothing changed yet"); // SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler. let reg2 = unsafe { gix::interrupt::init_handler(2, || V2.store(true, Ordering::SeqCst)) } .expect("multi-initialization is OK"); assert!(!V2.load(Ordering::Relaxed)); signal_hook::low_level::raise(SIGTERM).expect("signal can be raised"); assert_eq!(V1.load(Ordering::Relaxed), 3, "the first trigger is invoked"); assert!(!V2.load(Ordering::Relaxed), "the second trigger was ignored"); reg2.auto_deregister(); reg1.with_reset(true).auto_deregister(); assert!( !gix::interrupt::is_triggered(), "the deregistration succeeded and this is an optional side-effect" ); Ok(()) }}
#[cfg(feature = "interrupt")]
mod needs_feature {
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use signal_hook::consts::SIGTERM;
#[test]
fn multi_registration() -> gix_testtools::Result {
static V1: AtomicUsize = AtomicUsize::new(0);
static V2: AtomicBool = AtomicBool::new(false);
// SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler.
let reg1 = unsafe {
gix::interrupt::init_handler(3, || {
V1.fetch_add(1, Ordering::SeqCst);
})
}
.expect("succeeds");
assert!(!gix::interrupt::is_triggered());
assert_eq!(V1.load(Ordering::Relaxed), 0);
// SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler.
let reg2 = unsafe { gix::interrupt::init_handler(2, || V2.store(true, Ordering::SeqCst)) }
.expect("multi-initialization is OK");
assert!(!V2.load(Ordering::Relaxed));
signal_hook::low_level::raise(SIGTERM).expect("signal can be raised");
assert!(gix::interrupt::is_triggered(), "this happens automatically");
assert_eq!(V1.load(Ordering::Relaxed), 1, "the first trigger is invoked");
assert!(!V2.load(Ordering::Relaxed), "the second trigger was ignored");
reg1.deregister()?;
signal_hook::low_level::raise(SIGTERM).expect("signal can be raised");
assert_eq!(V1.load(Ordering::Relaxed), 2, "the first trigger is still invoked");
assert!(gix::interrupt::is_triggered(), "this happens automatically");
// now the registration is actually removed.
reg2.with_reset(true).deregister()?;
assert!(
!gix::interrupt::is_triggered(),
"the deregistration succeeded and this is an optional side-effect"
);
// SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler.
let reg1 = unsafe {
gix::interrupt::init_handler(3, || {
V1.fetch_add(1, Ordering::SeqCst);
})
}
.expect("succeeds");
assert_eq!(V1.load(Ordering::Relaxed), 2, "nothing changed yet");
// SAFETY: The closure doesn't use mutexes or memory allocation, so it should be safe to call from a signal handler.
let reg2 = unsafe { gix::interrupt::init_handler(2, || V2.store(true, Ordering::SeqCst)) }
.expect("multi-initialization is OK");
assert!(!V2.load(Ordering::Relaxed));
signal_hook::low_level::raise(SIGTERM).expect("signal can be raised");
assert_eq!(V1.load(Ordering::Relaxed), 3, "the first trigger is invoked");
assert!(!V2.load(Ordering::Relaxed), "the second trigger was ignored");
reg2.auto_deregister();
reg1.with_reset(true).auto_deregister();
assert!(
!gix::interrupt::is_triggered(),
"the deregistration succeeded and this is an optional side-effect"
);
Ok(())
}
}