Newtype SignalHandlers (#8089)

This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-06-14 13:53:18 +09:00
1 parent f34cfca1f3
commit a895eeed00
4 files changed
+40 -15

No files matched your search

+28 -7
View File
@@ -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<RefCell<[Option<PyObjectRef>; 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<isize> {
let handle = SIGINT_EVENT.load(Ordering::Acquire);
if handle == 0 { None } else { Some(handle) }
}
pub struct SignalHandlers(Box<RefCell<[Option<PyObjectRef>; NSIG]>>);
impl Default for SignalHandlers {
fn default() -> Self {
Self(Box::new(const { RefCell::new([const { None }; NSIG]) }))
}
}
impl Deref for SignalHandlers {
type Target = Box<RefCell<[Option<PyObjectRef>; NSIG]>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SignalHandlers {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
+7 -4
View File
@@ -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());
+1 -1
View File
@@ -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<PyObjectRef> = vm.state.after_forkers_child.lock().clone();
+4 -3
View File
@@ -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<PyObjectRef>,
pub use_tracing: Cell<bool>,
pub recursion_limit: Cell<usize>,
pub(crate) signal_handlers: OnceCell<Box<RefCell<[Option<PyObjectRef>; signal::NSIG]>>>,
pub(crate) signal_handlers: OnceCell<SignalHandlers>,
pub(crate) signal_rx: Option<signal::UserSignalReceiver>,
pub repr_guards: RefCell<HashSet<usize>>,
pub state: PyRc<PyGlobalState>,
@@ -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,