mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -33,6 +33,25 @@ dependencies = [
|
||||
"scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arr_macro"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arr_macro_impl"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.11"
|
||||
@@ -1011,6 +1030,7 @@ dependencies = [
|
||||
name = "rustpython-vm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1856,6 +1876,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d262b83f2f573121554ad6e764cd444303df85d86e5fcebc81903ddcf8dd3a97"
|
||||
"checksum arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8decbe97ffec939e44228d91e5d0829ceb1616c6ed0984c09df164b1e7ebaafc"
|
||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||
"checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
|
||||
44
tests/snippets/stdlib_signal.py
Normal file
44
tests/snippets/stdlib_signal.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import signal
|
||||
import time
|
||||
import sys
|
||||
from testutils import assert_raises
|
||||
|
||||
assert_raises(TypeError, lambda: signal.signal(signal.SIGINT, 2))
|
||||
|
||||
signals = []
|
||||
|
||||
def handler(signum, frame):
|
||||
signals.append(signum)
|
||||
|
||||
|
||||
signal.signal(signal.SIGILL, signal.SIG_IGN);
|
||||
assert signal.getsignal(signal.SIGILL) is signal.SIG_IGN
|
||||
|
||||
old_signal = signal.signal(signal.SIGILL, signal.SIG_DFL)
|
||||
assert old_signal is signal.SIG_IGN
|
||||
assert signal.getsignal(signal.SIGILL) is signal.SIG_DFL
|
||||
|
||||
|
||||
# unix
|
||||
if "win" not in sys.platform:
|
||||
signal.signal(signal.SIGALRM, handler)
|
||||
assert signal.getsignal(signal.SIGALRM) is handler
|
||||
|
||||
signal.alarm(1)
|
||||
time.sleep(2.0)
|
||||
assert signals == [signal.SIGALRM]
|
||||
|
||||
signal.signal(signal.SIGALRM, signal.SIG_IGN)
|
||||
signal.alarm(1)
|
||||
time.sleep(2.0)
|
||||
|
||||
assert signals == [signal.SIGALRM]
|
||||
|
||||
signal.signal(signal.SIGALRM, handler)
|
||||
signal.alarm(1)
|
||||
time.sleep(2.0)
|
||||
|
||||
assert signals == [signal.SIGALRM, signal.SIGALRM]
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ bitflags = "1.1"
|
||||
libc = "0.2"
|
||||
nix = "0.14.1"
|
||||
wtf8 = "0.0.3"
|
||||
arr_macro = "0.1.2"
|
||||
|
||||
flame = { version = "0.2", optional = true }
|
||||
flamer = { version = "0.3", optional = true }
|
||||
|
||||
@@ -23,6 +23,9 @@ use crate::vm::VirtualMachine;
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::stdlib::signal::check_signals;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Block {
|
||||
/// The type of block.
|
||||
@@ -163,6 +166,10 @@ impl Frame {
|
||||
/// Execute a single instruction.
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn execute_instruction(&self, vm: &VirtualMachine) -> FrameResult {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
check_signals(vm);
|
||||
}
|
||||
let instruction = self.fetch_instruction();
|
||||
|
||||
flame_guard!(format!("Frame::execute_instruction({:?})", instruction));
|
||||
|
||||
@@ -38,6 +38,8 @@ pub mod io;
|
||||
mod os;
|
||||
#[cfg(all(unix, not(any(target_os = "android", target_os = "redox"))))]
|
||||
mod pwd;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod signal;
|
||||
|
||||
use crate::pyobject::PyObjectRef;
|
||||
|
||||
@@ -92,6 +94,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
modules.insert("_io".to_string(), Box::new(io::make_module));
|
||||
modules.insert("_os".to_string(), Box::new(os::make_module));
|
||||
modules.insert("socket".to_string(), Box::new(socket::make_module));
|
||||
modules.insert("signal".to_string(), Box::new(signal::make_module));
|
||||
}
|
||||
|
||||
// Unix-only
|
||||
|
||||
165
vm/src/stdlib/signal.rs
Normal file
165
vm/src/stdlib/signal.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use crate::obj::objint::PyIntRef;
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
use arr_macro::arr;
|
||||
|
||||
#[cfg(unix)]
|
||||
use nix::unistd::alarm as sig_alarm;
|
||||
|
||||
use libc;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
use libc::{SIG_DFL, SIG_ERR, SIG_IGN};
|
||||
|
||||
#[cfg(windows)]
|
||||
const SIG_DFL: libc::sighandler_t = 0;
|
||||
#[cfg(windows)]
|
||||
const SIG_IGN: libc::sighandler_t = 1;
|
||||
#[cfg(windows)]
|
||||
const SIG_ERR: libc::sighandler_t = !0;
|
||||
|
||||
const NSIG: usize = 64;
|
||||
|
||||
// We cannot use the NSIG const in the arr macro. This will fail compilation if NSIG is different.
|
||||
static mut TRIGGERS: [AtomicBool; NSIG] = arr![AtomicBool::new(false); 64];
|
||||
|
||||
extern "C" fn run_signal(signum: i32) {
|
||||
unsafe {
|
||||
TRIGGERS[signum as usize].store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
fn signal(
|
||||
signalnum: PyIntRef,
|
||||
handler: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<PyObjectRef>> {
|
||||
if !vm.isinstance(&handler, &vm.ctx.function_type())?
|
||||
&& !vm.isinstance(&handler, &vm.ctx.bound_method_type())?
|
||||
&& !vm.isinstance(&handler, &vm.ctx.builtin_function_or_method_type())?
|
||||
{
|
||||
return Err(vm.new_type_error("Hanlder must be callable".to_string()));
|
||||
}
|
||||
let signal_module = vm.import("signal", &vm.ctx.new_tuple(vec![]), 0)?;
|
||||
let sig_dfl = vm.get_attribute(signal_module.clone(), "SIG_DFL")?;
|
||||
let sig_ign = vm.get_attribute(signal_module, "SIG_IGN")?;
|
||||
let signalnum = signalnum.as_bigint().to_i32().unwrap();
|
||||
check_signals(vm);
|
||||
let sig_handler = if handler.is(&sig_dfl) {
|
||||
SIG_DFL
|
||||
} else if handler.is(&sig_ign) {
|
||||
SIG_IGN
|
||||
} else {
|
||||
run_signal as libc::sighandler_t
|
||||
};
|
||||
let old = unsafe { libc::signal(signalnum, sig_handler) };
|
||||
if old == SIG_ERR {
|
||||
return Err(vm.new_os_error("Failed to set signal".to_string()));
|
||||
}
|
||||
let old_handler = vm.signal_handlers.borrow_mut().insert(signalnum, handler);
|
||||
Ok(old_handler)
|
||||
}
|
||||
|
||||
fn getsignal(signalnum: PyIntRef, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
|
||||
let signalnum = signalnum.as_bigint().to_i32().unwrap();
|
||||
Ok(vm.signal_handlers.borrow_mut().get(&signalnum).cloned())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn alarm(time: PyIntRef, _vm: &VirtualMachine) -> u32 {
|
||||
let time = time.as_bigint().to_u32().unwrap();
|
||||
let prev_time = if time == 0 {
|
||||
sig_alarm::cancel()
|
||||
} else {
|
||||
sig_alarm::set(time)
|
||||
};
|
||||
prev_time.unwrap_or(0)
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
pub fn check_signals(vm: &VirtualMachine) {
|
||||
for signum in 1..NSIG {
|
||||
let triggerd = unsafe { TRIGGERS[signum].swap(false, Ordering::Relaxed) };
|
||||
if triggerd {
|
||||
let handler = vm
|
||||
.signal_handlers
|
||||
.borrow()
|
||||
.get(&(signum as i32))
|
||||
.expect("Handler should be set")
|
||||
.clone();
|
||||
vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()])
|
||||
.expect("Test");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn stub_func(_vm: &VirtualMachine) -> PyResult {
|
||||
panic!("Do not use directly");
|
||||
}
|
||||
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let sig_dfl = ctx.new_rustfunc(stub_func);
|
||||
let sig_ign = ctx.new_rustfunc(stub_func);
|
||||
|
||||
let module = py_module!(vm, "signal", {
|
||||
"signal" => ctx.new_rustfunc(signal),
|
||||
"getsignal" => ctx.new_rustfunc(getsignal),
|
||||
"SIG_DFL" => sig_dfl,
|
||||
"SIG_IGN" => sig_ign,
|
||||
"SIGABRT" => ctx.new_int(libc::SIGABRT as u8),
|
||||
"SIGFPE" => ctx.new_int(libc::SIGFPE as u8),
|
||||
"SIGILL" => ctx.new_int(libc::SIGILL as u8),
|
||||
"SIGINT" => ctx.new_int(libc::SIGINT as u8),
|
||||
"SIGSEGV" => ctx.new_int(libc::SIGSEGV as u8),
|
||||
"SIGTERM" => ctx.new_int(libc::SIGTERM as u8),
|
||||
});
|
||||
extend_module_platform_specific(vm, module)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
extend_module!(vm, module, {
|
||||
"alarm" => ctx.new_rustfunc(alarm),
|
||||
"SIGHUP" => ctx.new_int(libc::SIGHUP as u8),
|
||||
"SIGQUIT" => ctx.new_int(libc::SIGQUIT as u8),
|
||||
"SIGTRAP" => ctx.new_int(libc::SIGTRAP as u8),
|
||||
"SIGBUS" => ctx.new_int(libc::SIGBUS as u8),
|
||||
"SIGKILL" => ctx.new_int(libc::SIGKILL as u8),
|
||||
"SIGUSR1" => ctx.new_int(libc::SIGUSR1 as u8),
|
||||
"SIGUSR2" => ctx.new_int(libc::SIGUSR2 as u8),
|
||||
"SIGPIPE" => ctx.new_int(libc::SIGPIPE as u8),
|
||||
"SIGALRM" => ctx.new_int(libc::SIGALRM as u8),
|
||||
"SIGSTKFLT" => ctx.new_int(libc::SIGSTKFLT as u8),
|
||||
"SIGCHLD" => ctx.new_int(libc::SIGCHLD as u8),
|
||||
"SIGCONT" => ctx.new_int(libc::SIGCONT as u8),
|
||||
"SIGSTOP" => ctx.new_int(libc::SIGSTOP as u8),
|
||||
"SIGTSTP" => ctx.new_int(libc::SIGTSTP as u8),
|
||||
"SIGTTIN" => ctx.new_int(libc::SIGTTIN as u8),
|
||||
"SIGTTOU" => ctx.new_int(libc::SIGTTOU as u8),
|
||||
"SIGURG" => ctx.new_int(libc::SIGURG as u8),
|
||||
"SIGXCPU" => ctx.new_int(libc::SIGXCPU as u8),
|
||||
"SIGXFSZ" => ctx.new_int(libc::SIGXFSZ as u8),
|
||||
"SIGVTALRM" => ctx.new_int(libc::SIGVTALRM as u8),
|
||||
"SIGPROF" => ctx.new_int(libc::SIGPROF as u8),
|
||||
"SIGWINCH" => ctx.new_int(libc::SIGWINCH as u8),
|
||||
"SIGIO" => ctx.new_int(libc::SIGIO as u8),
|
||||
"SIGPWR" => ctx.new_int(libc::SIGPWR as u8),
|
||||
"SIGSYS" => ctx.new_int(libc::SIGSYS as u8),
|
||||
});
|
||||
|
||||
module
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn extend_module_platform_specific(_vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
|
||||
module
|
||||
}
|
||||
@@ -62,6 +62,7 @@ pub struct VirtualMachine {
|
||||
pub trace_func: RefCell<PyObjectRef>,
|
||||
pub use_tracing: RefCell<bool>,
|
||||
pub settings: PySettings,
|
||||
pub signal_handlers: RefCell<HashMap<i32, PyObjectRef>>,
|
||||
}
|
||||
|
||||
/// Struct containing all kind of settings for the python vm.
|
||||
@@ -160,6 +161,7 @@ impl VirtualMachine {
|
||||
trace_func,
|
||||
use_tracing: RefCell::new(false),
|
||||
settings,
|
||||
signal_handlers: Default::default(),
|
||||
};
|
||||
|
||||
builtins::make_module(&vm, builtins.clone());
|
||||
|
||||
Reference in New Issue
Block a user