Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions crates/vm/src/signal.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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.
Expand Down Expand Up @@ -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
}
}
11 changes: 7 additions & 4 deletions crates/vm/src/stdlib/_signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -247,15 +250,15 @@ 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)
}

#[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());
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/stdlib/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
7 changes: 4 additions & 3 deletions crates/vm/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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,
Expand Down
Loading