FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix: signal.SIGINT and signal() raise NotImplementedError on wasi by jiwahn · Pull Request #8986 · RustPython/RustPython · GitHub

Repository navigation

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

Filter by extension

Filter by extension .a  (1) .md  (1) .py  (1) .rs  (4) .toml  (1) All 5 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
3 changes: 3 additions & 0 deletions .cargo/config.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ rustflags = ["--cfg=getrandom_backend=\"wasm_js\""]
# Enforce a 1 MB stack limit for WASI targets.
# (Runaway heap growth is fixed by the smaller DataStack chunk
# and the size‑optimized wasm‑release profile.)

[target.wasm32-wasip1]
rustflags = [
"-C", "link-arg=-zstack-size=1048576",
"-L", "crates/host_env/vendor/wasm32-wasip1",
"-l", "wasi-emulated-signal",
]

[target.wasm32-wasip2]
Expand Down
2 changes: 1 addition & 1 deletion crates/host_env/src/lib.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub mod pwd;
pub mod resource;
#[cfg(all(unix, not(target_os = "redox"), not(target_os = "android")))]
pub mod shm;
#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
pub mod signal;
pub mod time;

Expand Down
79 changes: 75 additions & 4 deletions crates/host_env/src/signal.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(any(unix, windows))]
use std::io;
#[cfg(windows)]
use std::sync::Once;
Expand All @@ -13,13 +14,83 @@ pub use libc::sighandler_t;
#[cfg(unix)]
pub use libc::{SIG_DFL, SIG_ERR, SIG_IGN};

#[cfg(not(unix))]
#[cfg(not(any(unix, target_os = "wasi")))]
pub const SIG_DFL: libc::sighandler_t = 0;
#[cfg(not(unix))]
#[cfg(not(any(unix, target_os = "wasi")))]
pub const SIG_IGN: libc::sighandler_t = 1;
#[cfg(not(unix))]
#[cfg(not(any(unix, target_os = "wasi")))]
pub const SIG_ERR: libc::sighandler_t = -1 as _;

/// wasi-libc's userspace emulation of `signal()`/`raise()`, linked from
/// `libwasi-emulated-signal` (see `crates/host_env/vendor/wasm32-wasip1`).
/// WebAssembly has no asynchronous signal delivery, so this is a
/// synchronous, in-process handler table: a handler only runs when this
/// process's own code calls `raise()`, never from an outside interrupt.
/// Numbering matches wasi-libc's `bits/signal.h`, the same values CPython's
/// WASI build gets by linking the same library.
#[cfg(target_os = "wasi")]
mod wasm {
use std::io;

#[allow(non_camel_case_types)]
pub type sighandler_t = usize;

pub const SIG_DFL: sighandler_t = 0;
pub const SIG_IGN: sighandler_t = 1;
pub const SIG_ERR: sighandler_t = -1isize as usize;

pub const SIGINT: i32 = 2;
pub const SIGILL: i32 = 4;
pub const SIGABRT: i32 = 6;
pub const SIGFPE: i32 = 8;
pub const SIGSEGV: i32 = 11;
pub const SIGTERM: i32 = 15;

unsafe extern "C" {
fn signal(signum: i32, handler: sighandler_t) -> sighandler_t;
fn raise(signum: i32) -> i32;
}

/// # Safety
///
/// The caller must ensure `signalnum` is a valid platform signal number.
pub unsafe fn probe_handler(signalnum: i32) -> Option<sighandler_t> {
let handler = unsafe { signal(signalnum, SIG_IGN) };
if handler == SIG_ERR {
None
} else {
unsafe { signal(signalnum, handler) };
Some(handler)
}
}

/// # Safety
///
/// The caller must ensure `signalnum` is a valid platform signal number and
/// `handler` is accepted by the platform signal ABI.
pub unsafe fn install_handler(
signalnum: i32,
handler: sighandler_t,
) -> io::Result<sighandler_t> {
let old = unsafe { signal(signalnum, handler) };
if old == SIG_ERR {
return Err(io::Error::last_os_error());
}
Ok(old)
}

pub fn raise_signal(signalnum: i32) -> io::Result<()> {
if unsafe { raise(signalnum) } == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
}

#[cfg(target_os = "wasi")]
pub use wasm::*;

#[cfg(unix)]
pub use libc::{SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK};

Expand Down Expand Up @@ -320,7 +391,7 @@ pub fn notify_signal(
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
pub fn notify_signal(signum: i32, wakeup_fd: i32) {
if wakeup_fd == -1 {
return;
Expand Down
16 changes: 16 additions & 0 deletions crates/host_env/vendor/wasm32-wasip1/README.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

👍

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Vendored wasi-libc emulation library

`libwasi-emulated-signal.a` is a prebuilt static library from
[wasi-sdk](https://github.com/WebAssembly/wasi-sdk), providing wasi-libc's
userspace emulation of `signal()`/`raise()` for `wasm32-wasip1` (WebAssembly
has no asynchronous signal delivery, so this is a synchronous, in-process
handler table, not a real OS signal mechanism).

CPython's own WASI build links the same library
(`configure.ac`'s `_WASI_EMULATED_SIGNAL` case).

- Source: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-34/wasi-sysroot-34.0.tar.gz
(path: `lib/wasm32-wasip1/libwasi-emulated-signal.a`)
- License: Apache-2.0 WITH LLVM-exception (same as wasi-libc)
- sha256: see below
becc35b856608fb9282d94c70166796e4d7b21e4e1057e625725306e765eb035 crates/host_env/vendor/wasm32-wasip1/libwasi-emulated-signal.a
Binary file not shown.
4 changes: 4 additions & 0 deletions crates/vm/src/signal.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ impl SignalNum {
#[allow(dead_code, reason = "Not used on all platforms")]
pub(crate) const SIGINT: Self = Self(libc::SIGINT);

#[cfg(all(target_os = "wasi", feature = "host_env"))]
#[allow(dead_code, reason = "Not used on all platforms")]
pub(crate) const SIGINT: Self = Self(rustpython_host_env::signal::SIGINT);

/// Construct [`Self`] without any validation on the signalnum value.
///
/// # Safety
Expand Down
26 changes: 13 additions & 13 deletions crates/vm/src/stdlib/_signal.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) mod _signal {
use core::sync::atomic::{self, Ordering};

cfg_select! {
any(unix, windows) => {
any(unix, windows, target_os = "wasi") => {
use crate::convert::{IntoPyException, TryFromBorrowedObject};
use rustpython_host_env::signal as host_signal;
}
Expand Down Expand Up @@ -73,11 +73,11 @@ pub(crate) mod _signal {
}
}

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
#[allow(unused_imports)]
pub use host_signal::SIG_ERR;

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
#[pyattr]
pub use host_signal::{SIG_DFL, SIG_IGN};

Expand All @@ -86,22 +86,22 @@ pub(crate) mod _signal {
#[pyattr]
use host_signal::{SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK};

#[cfg(not(any(unix, windows)))]
#[cfg(not(any(unix, windows, target_os = "wasi")))]
#[pyattr]
pub const SIG_DFL: sighandler_t = 0;

#[cfg(not(any(unix, windows)))]
#[cfg(not(any(unix, windows, target_os = "wasi")))]
#[pyattr]
pub const SIG_IGN: sighandler_t = 1;

#[cfg(not(any(unix, windows)))]
#[cfg(not(any(unix, windows, target_os = "wasi")))]
#[allow(dead_code)]
pub const SIG_ERR: sighandler_t = -1 as _;

#[pyattr]
use crate::signal::NSIG;

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
#[pyattr]
pub use host_signal::{SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM};

Expand Down Expand Up @@ -160,7 +160,7 @@ pub(crate) mod _signal {
const _: () = assert!(SignalNum::VALID_RANGE.start.is_positive());
const _: () = assert!(SignalNum::VALID_RANGE.end.is_positive());

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
pub(super) fn init_signal_handlers(
module: &Py<crate::builtins::PyModule>,
vm: &VirtualMachine,
Expand Down Expand Up @@ -199,7 +199,7 @@ pub(crate) mod _signal {
}
}

#[cfg(not(any(unix, windows)))]
#[cfg(not(any(unix, windows, target_os = "wasi")))]
#[pyfunction]
pub fn signal(
_signalnum: i32,
Expand All @@ -209,7 +209,7 @@ pub(crate) mod _signal {
Err(vm.new_not_implemented_error("signal is not implemented on this platform"))
}

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
#[pyfunction]
pub fn signal(
signalnum: SignalNum,
Expand Down Expand Up @@ -401,7 +401,7 @@ pub(crate) mod _signal {
host_signal::siginterrupt(signalnum.into(), flag).map_err(|_| vm.new_last_errno_error())
}

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
#[pyfunction]
fn raise_signal(signalnum: i32, vm: &VirtualMachine) -> PyResult<()> {
let signalnum = SignalNum::try_from(signalnum).map_err(cfg_select! {
Expand Down Expand Up @@ -506,7 +506,7 @@ pub(crate) mod _signal {
sigset_to_pyset(old_mask, vm)
}

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
pub extern "C" fn run_signal(signum: i32) {
signal::TRIGGERS[signum as usize].store(true, Ordering::Relaxed);
signal::set_triggered();
Expand Down Expand Up @@ -535,7 +535,7 @@ pub(crate) mod _signal {
) -> PyResult<()> {
__module_exec(vm, module);

#[cfg(any(unix, windows))]
#[cfg(any(unix, windows, target_os = "wasi"))]
init_signal_handlers(module, vm);

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions extra_tests/snippets/stdlib_signal.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def handler(signum, frame):
assert signal.getsignal(signal.SIGILL) is signal.SIG_DFL


# unix
if "win" not in sys.platform:
# unix, and not WASI
if "win" not in sys.platform and sys.platform != "wasi":
signal.signal(signal.SIGALRM, handler)
assert signal.getsignal(signal.SIGALRM) is handler

Expand Down
Loading

Back | FazBrowse Home | New Git URL