diff --git a/vm/src/signal.rs b/vm/src/signal.rs index 0da742e1e..0f90742dd 100644 --- a/vm/src/signal.rs +++ b/vm/src/signal.rs @@ -3,7 +3,7 @@ use crate::{PyObjectRef, PyResult, VirtualMachine}; use std::sync::atomic::{AtomicBool, Ordering}; pub const NSIG: usize = 64; -pub(crate) static ANY_TRIGGERED: AtomicBool = AtomicBool::new(false); +static ANY_TRIGGERED: AtomicBool = AtomicBool::new(false); // hack to get around const array repeat expressions, rust issue #79270 #[allow(clippy::declare_interior_mutable_const)] const ATOMIC_FALSE: AtomicBool = AtomicBool::new(false); @@ -12,24 +12,21 @@ pub(crate) static TRIGGERS: [AtomicBool; NSIG] = [ATOMIC_FALSE; NSIG]; #[cfg_attr(feature = "flame-it", flame)] #[inline(always)] pub fn check_signals(vm: &VirtualMachine) -> PyResult<()> { - let signal_handlers = match &vm.signal_handlers { - Some(h) => h, - None => return Ok(()), - }; - - if !ANY_TRIGGERED.load(Ordering::Relaxed) { + if vm.signal_handlers.is_none() { return Ok(()); } - ANY_TRIGGERED.store(false, Ordering::Relaxed); - trigger_signals(&signal_handlers.borrow(), vm) + if !ANY_TRIGGERED.swap(false, Ordering::Acquire) { + return Ok(()); + } + + trigger_signals(vm) } #[inline(never)] #[cold] -fn trigger_signals( - signal_handlers: &[Option; NSIG], - vm: &VirtualMachine, -) -> PyResult<()> { +fn trigger_signals(vm: &VirtualMachine) -> PyResult<()> { + // unwrap should never fail since we check above + let signal_handlers = vm.signal_handlers.as_ref().unwrap().borrow(); for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) { let triggered = trigger.swap(false, Ordering::Relaxed); if triggered { @@ -42,3 +39,7 @@ fn trigger_signals( } Ok(()) } + +pub(crate) fn set_triggered() { + ANY_TRIGGERED.store(true, Ordering::Release); +} diff --git a/vm/src/stdlib/signal.rs b/vm/src/stdlib/signal.rs index a47906b3d..15a77e995 100644 --- a/vm/src/stdlib/signal.rs +++ b/vm/src/stdlib/signal.rs @@ -36,9 +36,8 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { #[pymodule] pub(crate) mod _signal { use crate::{ - function::IntoPyException, - signal::{check_signals, ANY_TRIGGERED, TRIGGERS}, - PyObjectRef, PyResult, TryFromBorrowedObject, VirtualMachine, + function::IntoPyException, signal, PyObjectRef, PyResult, TryFromBorrowedObject, + VirtualMachine, }; use std::sync::atomic::{self, Ordering}; @@ -128,7 +127,7 @@ pub(crate) mod _signal { .to_owned(), )), }; - check_signals(vm)?; + signal::check_signals(vm)?; let old = unsafe { libc::signal(signalnum, sig_handler) }; if old == SIG_ERR { @@ -256,8 +255,8 @@ pub(crate) mod _signal { } extern "C" fn run_signal(signum: i32) { - TRIGGERS[signum as usize].store(true, Ordering::Relaxed); - ANY_TRIGGERED.store(true, Ordering::SeqCst); + signal::TRIGGERS[signum as usize].store(true, Ordering::Relaxed); + signal::set_triggered(); let wakeup_fd = WAKEUP.load(Ordering::Relaxed); if wakeup_fd != INVALID_WAKEUP { let sigbyte = signum as u8;