From 9198c2639a7821b5c4d831b18c0fadbd4ac47fad Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Fri, 12 Jun 2026 15:57:06 +0300 Subject: [PATCH] Newtype SignalHandlers --- crates/vm/src/signal.rs | 35 ++++++++++++++++++++++++++------- crates/vm/src/stdlib/_signal.rs | 11 +++++++---- crates/vm/src/stdlib/posix.rs | 2 +- crates/vm/src/vm/mod.rs | 7 ++++--- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/crates/vm/src/signal.rs b/crates/vm/src/signal.rs index 50a887c1435..11fe4f21271 100644 --- a/crates/vm/src/signal.rs +++ b/crates/vm/src/signal.rs @@ -1,7 +1,10 @@ use crate::{PyObjectRef, PyResult, VirtualMachine}; -use alloc::fmt; -use core::cell::{Cell, RefCell}; -use core::sync::atomic::{AtomicBool, Ordering}; +use core::{ + cell::{Cell, RefCell}, + fmt, + ops::{Deref, DerefMut}, + sync::atomic::{AtomicBool, Ordering}, +}; use std::sync::mpsc; #[cfg(windows)] @@ -22,10 +25,6 @@ pub(crate) static TRIGGERS: [AtomicBool; NSIG] = [ATOMIC_FALSE; NSIG]; #[cfg(windows)] static SIGINT_EVENT: AtomicIsize = AtomicIsize::new(0); -pub(crate) fn new_signal_handlers() -> Box; NSIG]>> { - Box::new(const { RefCell::new([const { None }; NSIG]) }) -} - thread_local! { /// Prevent recursive signal handler invocation. When a Python signal /// handler is running, new signals are deferred until it completes. @@ -190,3 +189,25 @@ pub fn get_sigint_event() -> Option { let handle = SIGINT_EVENT.load(Ordering::Acquire); if handle == 0 { None } else { Some(handle) } } + +pub struct SignalHandlers(Box; NSIG]>>); + +impl Default for SignalHandlers { + fn default() -> Self { + Self(Box::new(const { RefCell::new([const { None }; NSIG]) })) + } +} + +impl Deref for SignalHandlers { + type Target = Box; NSIG]>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for SignalHandlers { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/crates/vm/src/stdlib/_signal.rs b/crates/vm/src/stdlib/_signal.rs index 191f67d090f..2d9eaa53a28 100644 --- a/crates/vm/src/stdlib/_signal.rs +++ b/crates/vm/src/stdlib/_signal.rs @@ -6,7 +6,10 @@ pub(crate) use _signal::module_def; pub(crate) mod _signal { #![allow(unreachable_pub)] - use crate::{Py, PyObjectRef, PyResult, VirtualMachine, signal}; + use crate::{ + Py, PyObjectRef, PyResult, VirtualMachine, + signal::{self, SignalHandlers}, + }; use core::{ ops::Range, sync::atomic::{self, Ordering}, @@ -193,7 +196,7 @@ pub(crate) mod _signal { }; vm.signal_handlers - .get_or_init(signal::new_signal_handlers) + .get_or_init(SignalHandlers::default) .borrow_mut()[signum as usize] = py_handler; } @@ -247,7 +250,7 @@ pub(crate) mod _signal { unsafe { host_signal::install_handler(signalnum, sig_handler) } .map_err(|_| vm.new_os_error("Failed to set signal"))?; - let signal_handlers = vm.signal_handlers.get_or_init(signal::new_signal_handlers); + let signal_handlers = vm.signal_handlers.get_or_init(SignalHandlers::default); let old_handler = signal_handlers.borrow_mut()[signalnum as usize].replace(handler); Ok(old_handler) } @@ -255,7 +258,7 @@ pub(crate) mod _signal { #[pyfunction] fn getsignal(signalnum: i32, vm: &VirtualMachine) -> PyResult { signal::assert_in_range(signalnum, vm)?; - let signal_handlers = vm.signal_handlers.get_or_init(signal::new_signal_handlers); + let signal_handlers = vm.signal_handlers.get_or_init(SignalHandlers::default); let handler = signal_handlers.borrow()[signalnum as usize] .clone() .unwrap_or_else(|| vm.ctx.none()); diff --git a/crates/vm/src/stdlib/posix.rs b/crates/vm/src/stdlib/posix.rs index 0a55cec4c3f..21576e8da2d 100644 --- a/crates/vm/src/stdlib/posix.rs +++ b/crates/vm/src/stdlib/posix.rs @@ -670,7 +670,7 @@ pub mod module { // Initialize signal handlers for the child's main thread. // When forked from a worker thread, the OnceCell is empty. vm.signal_handlers - .get_or_init(crate::signal::new_signal_handlers); + .get_or_init(crate::signal::SignalHandlers::default); // Phase 4: Run Python-level at-fork callbacks. let after_forkers_child: Vec = vm.state.after_forkers_child.lock().clone(); diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 0820ae2d8d9..699c751fcba 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -36,7 +36,8 @@ use crate::{ import, protocol::PyIterIter, scope::Scope, - signal, stdlib, + signal::{self, SignalHandlers}, + stdlib, warn::WarningsState, }; use alloc::{borrow::Cow, collections::BTreeMap}; @@ -82,7 +83,7 @@ pub struct VirtualMachine { pub trace_func: RefCell, pub use_tracing: Cell, pub recursion_limit: Cell, - pub(crate) signal_handlers: OnceCell; signal::NSIG]>>>, + pub(crate) signal_handlers: OnceCell, pub(crate) signal_rx: Option, pub repr_guards: RefCell>, pub state: PyRc, @@ -723,7 +724,7 @@ impl VirtualMachine { let importlib = ctx.none(); let profile_func = RefCell::new(ctx.none()); let trace_func = RefCell::new(ctx.none()); - let signal_handlers = OnceCell::from(signal::new_signal_handlers()); + let signal_handlers = OnceCell::from(SignalHandlers::default()); let vm = Self { builtins,