mirror of
https://github.com/denoland/deno.git
synced 2024-12-27 01:29:14 -05:00
28b362adfc
<!-- Before submitting a PR, please read https://docs.deno.com/runtime/manual/references/contributing 1. Give the PR a descriptive title. Examples of good title: - fix(std/http): Fix race condition in server - docs(console): Update docstrings - feat(doc): Handle nested reexports Examples of bad title: - fix #7123 - update docs - fix bugs 2. Ensure there is a related issue and it is referenced in the PR text. 3. Ensure there are tests that cover the changes. 4. Ensure `cargo test` passes. 5. Ensure `./tools/format.js` passes without changing files. 6. Ensure `./tools/lint.js` passes. 7. Open as a draft PR if your work is still in progress. The CI won't run all steps, but you can add '[ci]' to a commit message to force it to. 8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label. --> Fixes #22724. Fixes #7164. This does add a dependency on `signal-hook`, but it's just a higher level API on top of `signal-hook-registry` (which we and `tokio` already depend on) and doesn't add any transitive deps.
683 lines
16 KiB
Rust
683 lines
16 KiB
Rust
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
use deno_core::error::type_error;
|
|
use deno_core::error::AnyError;
|
|
use deno_core::op2;
|
|
use deno_core::AsyncRefCell;
|
|
use deno_core::CancelFuture;
|
|
use deno_core::CancelHandle;
|
|
use deno_core::OpState;
|
|
use deno_core::RcRef;
|
|
use deno_core::Resource;
|
|
use deno_core::ResourceId;
|
|
|
|
use std::borrow::Cow;
|
|
use std::cell::RefCell;
|
|
#[cfg(unix)]
|
|
use std::collections::BTreeMap;
|
|
use std::rc::Rc;
|
|
#[cfg(unix)]
|
|
use std::sync::atomic::AtomicBool;
|
|
#[cfg(unix)]
|
|
use std::sync::Arc;
|
|
|
|
#[cfg(unix)]
|
|
use tokio::signal::unix::signal;
|
|
#[cfg(unix)]
|
|
use tokio::signal::unix::Signal;
|
|
#[cfg(unix)]
|
|
use tokio::signal::unix::SignalKind;
|
|
#[cfg(windows)]
|
|
use tokio::signal::windows::ctrl_break;
|
|
#[cfg(windows)]
|
|
use tokio::signal::windows::ctrl_c;
|
|
#[cfg(windows)]
|
|
use tokio::signal::windows::CtrlBreak;
|
|
#[cfg(windows)]
|
|
use tokio::signal::windows::CtrlC;
|
|
|
|
deno_core::extension!(
|
|
deno_signal,
|
|
ops = [op_signal_bind, op_signal_unbind, op_signal_poll],
|
|
state = |state| {
|
|
#[cfg(unix)]
|
|
{
|
|
state.put(SignalState::default());
|
|
}
|
|
}
|
|
);
|
|
|
|
#[cfg(unix)]
|
|
#[derive(Default)]
|
|
struct SignalState {
|
|
enable_default_handlers: BTreeMap<libc::c_int, Arc<AtomicBool>>,
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
impl SignalState {
|
|
/// Disable the default signal handler for the given signal.
|
|
///
|
|
/// Returns the shared flag to enable the default handler later, and whether a default handler already existed.
|
|
fn disable_default_handler(
|
|
&mut self,
|
|
signo: libc::c_int,
|
|
) -> (Arc<AtomicBool>, bool) {
|
|
use std::collections::btree_map::Entry;
|
|
|
|
match self.enable_default_handlers.entry(signo) {
|
|
Entry::Occupied(entry) => {
|
|
let enable = entry.get();
|
|
enable.store(false, std::sync::atomic::Ordering::Release);
|
|
(enable.clone(), true)
|
|
}
|
|
Entry::Vacant(entry) => {
|
|
let enable = Arc::new(AtomicBool::new(false));
|
|
entry.insert(enable.clone());
|
|
(enable, false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
/// The resource for signal stream.
|
|
/// The second element is the waker of polling future.
|
|
struct SignalStreamResource {
|
|
signal: AsyncRefCell<Signal>,
|
|
enable_default_handler: Arc<AtomicBool>,
|
|
cancel: CancelHandle,
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
impl Resource for SignalStreamResource {
|
|
fn name(&self) -> Cow<str> {
|
|
"signal".into()
|
|
}
|
|
|
|
fn close(self: Rc<Self>) {
|
|
self.cancel.cancel();
|
|
}
|
|
}
|
|
|
|
// TODO: CtrlClose could be mapped to SIGHUP but that needs a
|
|
// tokio::windows::signal::CtrlClose type, or something from a different crate
|
|
#[cfg(windows)]
|
|
enum WindowsSignal {
|
|
Sigint(CtrlC),
|
|
Sigbreak(CtrlBreak),
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
impl From<CtrlC> for WindowsSignal {
|
|
fn from(ctrl_c: CtrlC) -> Self {
|
|
WindowsSignal::Sigint(ctrl_c)
|
|
}
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
impl From<CtrlBreak> for WindowsSignal {
|
|
fn from(ctrl_break: CtrlBreak) -> Self {
|
|
WindowsSignal::Sigbreak(ctrl_break)
|
|
}
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
impl WindowsSignal {
|
|
pub async fn recv(&mut self) -> Option<()> {
|
|
match self {
|
|
WindowsSignal::Sigint(ctrl_c) => ctrl_c.recv().await,
|
|
WindowsSignal::Sigbreak(ctrl_break) => ctrl_break.recv().await,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
struct SignalStreamResource {
|
|
signal: AsyncRefCell<WindowsSignal>,
|
|
cancel: CancelHandle,
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
impl Resource for SignalStreamResource {
|
|
fn name(&self) -> Cow<str> {
|
|
"signal".into()
|
|
}
|
|
|
|
fn close(self: Rc<Self>) {
|
|
self.cancel.cancel();
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "freebsd")]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGHUP" => Ok(1),
|
|
"SIGINT" => Ok(2),
|
|
"SIGQUIT" => Ok(3),
|
|
"SIGILL" => Ok(4),
|
|
"SIGTRAP" => Ok(5),
|
|
"SIGIOT" => Ok(6),
|
|
"SIGABRT" => Ok(6),
|
|
"SIGEMT" => Ok(7),
|
|
"SIGFPE" => Ok(8),
|
|
"SIGKILL" => Ok(9),
|
|
"SIGBUS" => Ok(10),
|
|
"SIGSEGV" => Ok(11),
|
|
"SIGSYS" => Ok(12),
|
|
"SIGPIPE" => Ok(13),
|
|
"SIGALRM" => Ok(14),
|
|
"SIGTERM" => Ok(15),
|
|
"SIGURG" => Ok(16),
|
|
"SIGSTOP" => Ok(17),
|
|
"SIGTSTP" => Ok(18),
|
|
"SIGCONT" => Ok(19),
|
|
"SIGCHLD" => Ok(20),
|
|
"SIGTTIN" => Ok(21),
|
|
"SIGTTOU" => Ok(22),
|
|
"SIGIO" => Ok(23),
|
|
"SIGXCPU" => Ok(24),
|
|
"SIGXFSZ" => Ok(25),
|
|
"SIGVTALRM" => Ok(26),
|
|
"SIGPROF" => Ok(27),
|
|
"SIGWINCH" => Ok(28),
|
|
"SIGINFO" => Ok(29),
|
|
"SIGUSR1" => Ok(30),
|
|
"SIGUSR2" => Ok(31),
|
|
"SIGTHR" => Ok(32),
|
|
"SIGLIBRT" => Ok(33),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "freebsd")]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
1 => Ok("SIGHUP"),
|
|
2 => Ok("SIGINT"),
|
|
3 => Ok("SIGQUIT"),
|
|
4 => Ok("SIGILL"),
|
|
5 => Ok("SIGTRAP"),
|
|
6 => Ok("SIGABRT"),
|
|
7 => Ok("SIGEMT"),
|
|
8 => Ok("SIGFPE"),
|
|
9 => Ok("SIGKILL"),
|
|
10 => Ok("SIGBUS"),
|
|
11 => Ok("SIGSEGV"),
|
|
12 => Ok("SIGSYS"),
|
|
13 => Ok("SIGPIPE"),
|
|
14 => Ok("SIGALRM"),
|
|
15 => Ok("SIGTERM"),
|
|
16 => Ok("SIGURG"),
|
|
17 => Ok("SIGSTOP"),
|
|
18 => Ok("SIGTSTP"),
|
|
19 => Ok("SIGCONT"),
|
|
20 => Ok("SIGCHLD"),
|
|
21 => Ok("SIGTTIN"),
|
|
22 => Ok("SIGTTOU"),
|
|
23 => Ok("SIGIO"),
|
|
24 => Ok("SIGXCPU"),
|
|
25 => Ok("SIGXFSZ"),
|
|
26 => Ok("SIGVTALRM"),
|
|
27 => Ok("SIGPROF"),
|
|
28 => Ok("SIGWINCH"),
|
|
29 => Ok("SIGINFO"),
|
|
30 => Ok("SIGUSR1"),
|
|
31 => Ok("SIGUSR2"),
|
|
32 => Ok("SIGTHR"),
|
|
33 => Ok("SIGLIBRT"),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "openbsd")]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGHUP" => Ok(1),
|
|
"SIGINT" => Ok(2),
|
|
"SIGQUIT" => Ok(3),
|
|
"SIGILL" => Ok(4),
|
|
"SIGTRAP" => Ok(5),
|
|
"SIGIOT" => Ok(6),
|
|
"SIGABRT" => Ok(6),
|
|
"SIGEMT" => Ok(7),
|
|
"SIGFPE" => Ok(8),
|
|
"SIGKILL" => Ok(9),
|
|
"SIGBUS" => Ok(10),
|
|
"SIGSEGV" => Ok(11),
|
|
"SIGSYS" => Ok(12),
|
|
"SIGPIPE" => Ok(13),
|
|
"SIGALRM" => Ok(14),
|
|
"SIGTERM" => Ok(15),
|
|
"SIGURG" => Ok(16),
|
|
"SIGSTOP" => Ok(17),
|
|
"SIGTSTP" => Ok(18),
|
|
"SIGCONT" => Ok(19),
|
|
"SIGCHLD" => Ok(20),
|
|
"SIGTTIN" => Ok(21),
|
|
"SIGTTOU" => Ok(22),
|
|
"SIGIO" => Ok(23),
|
|
"SIGXCPU" => Ok(24),
|
|
"SIGXFSZ" => Ok(25),
|
|
"SIGVTALRM" => Ok(26),
|
|
"SIGPROF" => Ok(27),
|
|
"SIGWINCH" => Ok(28),
|
|
"SIGINFO" => Ok(29),
|
|
"SIGUSR1" => Ok(30),
|
|
"SIGUSR2" => Ok(31),
|
|
"SIGTHR" => Ok(32),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "openbsd")]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
1 => Ok("SIGHUP"),
|
|
2 => Ok("SIGINT"),
|
|
3 => Ok("SIGQUIT"),
|
|
4 => Ok("SIGILL"),
|
|
5 => Ok("SIGTRAP"),
|
|
6 => Ok("SIGABRT"),
|
|
7 => Ok("SIGEMT"),
|
|
8 => Ok("SIGFPE"),
|
|
9 => Ok("SIGKILL"),
|
|
10 => Ok("SIGBUS"),
|
|
11 => Ok("SIGSEGV"),
|
|
12 => Ok("SIGSYS"),
|
|
13 => Ok("SIGPIPE"),
|
|
14 => Ok("SIGALRM"),
|
|
15 => Ok("SIGTERM"),
|
|
16 => Ok("SIGURG"),
|
|
17 => Ok("SIGSTOP"),
|
|
18 => Ok("SIGTSTP"),
|
|
19 => Ok("SIGCONT"),
|
|
20 => Ok("SIGCHLD"),
|
|
21 => Ok("SIGTTIN"),
|
|
22 => Ok("SIGTTOU"),
|
|
23 => Ok("SIGIO"),
|
|
24 => Ok("SIGXCPU"),
|
|
25 => Ok("SIGXFSZ"),
|
|
26 => Ok("SIGVTALRM"),
|
|
27 => Ok("SIGPROF"),
|
|
28 => Ok("SIGWINCH"),
|
|
29 => Ok("SIGINFO"),
|
|
30 => Ok("SIGUSR1"),
|
|
31 => Ok("SIGUSR2"),
|
|
32 => Ok("SIGTHR"),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(any(target_os = "android", target_os = "linux"))]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGHUP" => Ok(1),
|
|
"SIGINT" => Ok(2),
|
|
"SIGQUIT" => Ok(3),
|
|
"SIGILL" => Ok(4),
|
|
"SIGTRAP" => Ok(5),
|
|
"SIGIOT" => Ok(6),
|
|
"SIGABRT" => Ok(6),
|
|
"SIGBUS" => Ok(7),
|
|
"SIGFPE" => Ok(8),
|
|
"SIGKILL" => Ok(9),
|
|
"SIGUSR1" => Ok(10),
|
|
"SIGSEGV" => Ok(11),
|
|
"SIGUSR2" => Ok(12),
|
|
"SIGPIPE" => Ok(13),
|
|
"SIGALRM" => Ok(14),
|
|
"SIGTERM" => Ok(15),
|
|
"SIGSTKFLT" => Ok(16),
|
|
"SIGCHLD" => Ok(17),
|
|
"SIGCONT" => Ok(18),
|
|
"SIGSTOP" => Ok(19),
|
|
"SIGTSTP" => Ok(20),
|
|
"SIGTTIN" => Ok(21),
|
|
"SIGTTOU" => Ok(22),
|
|
"SIGURG" => Ok(23),
|
|
"SIGXCPU" => Ok(24),
|
|
"SIGXFSZ" => Ok(25),
|
|
"SIGVTALRM" => Ok(26),
|
|
"SIGPROF" => Ok(27),
|
|
"SIGWINCH" => Ok(28),
|
|
"SIGIO" => Ok(29),
|
|
"SIGPWR" => Ok(30),
|
|
"SIGSYS" => Ok(31),
|
|
_ => Err(type_error(format!("Invalid signal : {s}"))),
|
|
}
|
|
}
|
|
|
|
#[cfg(any(target_os = "android", target_os = "linux"))]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
1 => Ok("SIGHUP"),
|
|
2 => Ok("SIGINT"),
|
|
3 => Ok("SIGQUIT"),
|
|
4 => Ok("SIGILL"),
|
|
5 => Ok("SIGTRAP"),
|
|
6 => Ok("SIGABRT"),
|
|
7 => Ok("SIGBUS"),
|
|
8 => Ok("SIGFPE"),
|
|
9 => Ok("SIGKILL"),
|
|
10 => Ok("SIGUSR1"),
|
|
11 => Ok("SIGSEGV"),
|
|
12 => Ok("SIGUSR2"),
|
|
13 => Ok("SIGPIPE"),
|
|
14 => Ok("SIGALRM"),
|
|
15 => Ok("SIGTERM"),
|
|
16 => Ok("SIGSTKFLT"),
|
|
17 => Ok("SIGCHLD"),
|
|
18 => Ok("SIGCONT"),
|
|
19 => Ok("SIGSTOP"),
|
|
20 => Ok("SIGTSTP"),
|
|
21 => Ok("SIGTTIN"),
|
|
22 => Ok("SIGTTOU"),
|
|
23 => Ok("SIGURG"),
|
|
24 => Ok("SIGXCPU"),
|
|
25 => Ok("SIGXFSZ"),
|
|
26 => Ok("SIGVTALRM"),
|
|
27 => Ok("SIGPROF"),
|
|
28 => Ok("SIGWINCH"),
|
|
29 => Ok("SIGIO"),
|
|
30 => Ok("SIGPWR"),
|
|
31 => Ok("SIGSYS"),
|
|
_ => Err(type_error(format!("Invalid signal : {s}"))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGHUP" => Ok(1),
|
|
"SIGINT" => Ok(2),
|
|
"SIGQUIT" => Ok(3),
|
|
"SIGILL" => Ok(4),
|
|
"SIGTRAP" => Ok(5),
|
|
"SIGIOT" => Ok(6),
|
|
"SIGABRT" => Ok(6),
|
|
"SIGEMT" => Ok(7),
|
|
"SIGFPE" => Ok(8),
|
|
"SIGKILL" => Ok(9),
|
|
"SIGBUS" => Ok(10),
|
|
"SIGSEGV" => Ok(11),
|
|
"SIGSYS" => Ok(12),
|
|
"SIGPIPE" => Ok(13),
|
|
"SIGALRM" => Ok(14),
|
|
"SIGTERM" => Ok(15),
|
|
"SIGURG" => Ok(16),
|
|
"SIGSTOP" => Ok(17),
|
|
"SIGTSTP" => Ok(18),
|
|
"SIGCONT" => Ok(19),
|
|
"SIGCHLD" => Ok(20),
|
|
"SIGTTIN" => Ok(21),
|
|
"SIGTTOU" => Ok(22),
|
|
"SIGIO" => Ok(23),
|
|
"SIGXCPU" => Ok(24),
|
|
"SIGXFSZ" => Ok(25),
|
|
"SIGVTALRM" => Ok(26),
|
|
"SIGPROF" => Ok(27),
|
|
"SIGWINCH" => Ok(28),
|
|
"SIGINFO" => Ok(29),
|
|
"SIGUSR1" => Ok(30),
|
|
"SIGUSR2" => Ok(31),
|
|
_ => Err(type_error(format!("Invalid signal: {s}"))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
1 => Ok("SIGHUP"),
|
|
2 => Ok("SIGINT"),
|
|
3 => Ok("SIGQUIT"),
|
|
4 => Ok("SIGILL"),
|
|
5 => Ok("SIGTRAP"),
|
|
6 => Ok("SIGABRT"),
|
|
7 => Ok("SIGEMT"),
|
|
8 => Ok("SIGFPE"),
|
|
9 => Ok("SIGKILL"),
|
|
10 => Ok("SIGBUS"),
|
|
11 => Ok("SIGSEGV"),
|
|
12 => Ok("SIGSYS"),
|
|
13 => Ok("SIGPIPE"),
|
|
14 => Ok("SIGALRM"),
|
|
15 => Ok("SIGTERM"),
|
|
16 => Ok("SIGURG"),
|
|
17 => Ok("SIGSTOP"),
|
|
18 => Ok("SIGTSTP"),
|
|
19 => Ok("SIGCONT"),
|
|
20 => Ok("SIGCHLD"),
|
|
21 => Ok("SIGTTIN"),
|
|
22 => Ok("SIGTTOU"),
|
|
23 => Ok("SIGIO"),
|
|
24 => Ok("SIGXCPU"),
|
|
25 => Ok("SIGXFSZ"),
|
|
26 => Ok("SIGVTALRM"),
|
|
27 => Ok("SIGPROF"),
|
|
28 => Ok("SIGWINCH"),
|
|
29 => Ok("SIGINFO"),
|
|
30 => Ok("SIGUSR1"),
|
|
31 => Ok("SIGUSR2"),
|
|
_ => Err(type_error(format!("Invalid signal: {s}"))),
|
|
}
|
|
}
|
|
|
|
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGHUP" => Ok(1),
|
|
"SIGINT" => Ok(2),
|
|
"SIGQUIT" => Ok(3),
|
|
"SIGILL" => Ok(4),
|
|
"SIGTRAP" => Ok(5),
|
|
"SIGIOT" => Ok(6),
|
|
"SIGABRT" => Ok(6),
|
|
"SIGEMT" => Ok(7),
|
|
"SIGFPE" => Ok(8),
|
|
"SIGKILL" => Ok(9),
|
|
"SIGBUS" => Ok(10),
|
|
"SIGSEGV" => Ok(11),
|
|
"SIGSYS" => Ok(12),
|
|
"SIGPIPE" => Ok(13),
|
|
"SIGALRM" => Ok(14),
|
|
"SIGTERM" => Ok(15),
|
|
"SIGUSR1" => Ok(16),
|
|
"SIGUSR2" => Ok(17),
|
|
"SIGCLD" => Ok(18),
|
|
"SIGCHLD" => Ok(18),
|
|
"SIGPWR" => Ok(19),
|
|
"SIGWINCH" => Ok(20),
|
|
"SIGURG" => Ok(21),
|
|
"SIGPOLL" => Ok(22),
|
|
"SIGIO" => Ok(22),
|
|
"SIGSTOP" => Ok(23),
|
|
"SIGTSTP" => Ok(24),
|
|
"SIGCONT" => Ok(25),
|
|
"SIGTTIN" => Ok(26),
|
|
"SIGTTOU" => Ok(27),
|
|
"SIGVTALRM" => Ok(28),
|
|
"SIGPROF" => Ok(29),
|
|
"SIGXCPU" => Ok(30),
|
|
"SIGXFSZ" => Ok(31),
|
|
"SIGWAITING" => Ok(32),
|
|
"SIGLWP" => Ok(33),
|
|
"SIGFREEZE" => Ok(34),
|
|
"SIGTHAW" => Ok(35),
|
|
"SIGCANCEL" => Ok(36),
|
|
"SIGLOST" => Ok(37),
|
|
"SIGXRES" => Ok(38),
|
|
"SIGJVM1" => Ok(39),
|
|
"SIGJVM2" => Ok(40),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
1 => Ok("SIGHUP"),
|
|
2 => Ok("SIGINT"),
|
|
3 => Ok("SIGQUIT"),
|
|
4 => Ok("SIGILL"),
|
|
5 => Ok("SIGTRAP"),
|
|
6 => Ok("SIGABRT"),
|
|
7 => Ok("SIGEMT"),
|
|
8 => Ok("SIGFPE"),
|
|
9 => Ok("SIGKILL"),
|
|
10 => Ok("SIGBUS"),
|
|
11 => Ok("SIGSEGV"),
|
|
12 => Ok("SIGSYS"),
|
|
13 => Ok("SIGPIPE"),
|
|
14 => Ok("SIGALRM"),
|
|
15 => Ok("SIGTERM"),
|
|
16 => Ok("SIGUSR1"),
|
|
17 => Ok("SIGUSR2"),
|
|
18 => Ok("SIGCHLD"),
|
|
19 => Ok("SIGPWR"),
|
|
20 => Ok("SIGWINCH"),
|
|
21 => Ok("SIGURG"),
|
|
22 => Ok("SIGPOLL"),
|
|
23 => Ok("SIGSTOP"),
|
|
24 => Ok("SIGTSTP"),
|
|
25 => Ok("SIGCONT"),
|
|
26 => Ok("SIGTTIN"),
|
|
27 => Ok("SIGTTOU"),
|
|
28 => Ok("SIGVTALRM"),
|
|
29 => Ok("SIGPROF"),
|
|
30 => Ok("SIGXCPU"),
|
|
31 => Ok("SIGXFSZ"),
|
|
32 => Ok("SIGWAITING"),
|
|
33 => Ok("SIGLWP"),
|
|
34 => Ok("SIGFREEZE"),
|
|
35 => Ok("SIGTHAW"),
|
|
36 => Ok("SIGCANCEL"),
|
|
37 => Ok("SIGLOST"),
|
|
38 => Ok("SIGXRES"),
|
|
39 => Ok("SIGJVM1"),
|
|
40 => Ok("SIGJVM2"),
|
|
_ => Err(type_error(format!("Invalid signal : {}", s))),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
|
match s {
|
|
"SIGINT" => Ok(2),
|
|
"SIGBREAK" => Ok(21),
|
|
_ => Err(type_error(
|
|
"Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK).",
|
|
)),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
|
match s {
|
|
2 => Ok("SIGINT"),
|
|
21 => Ok("SIGBREAK"),
|
|
_ => Err(type_error(
|
|
"Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK).",
|
|
)),
|
|
}
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[op2(fast)]
|
|
#[smi]
|
|
fn op_signal_bind(
|
|
state: &mut OpState,
|
|
#[string] sig: &str,
|
|
) -> Result<ResourceId, AnyError> {
|
|
let signo = signal_str_to_int(sig)?;
|
|
if signal_hook_registry::FORBIDDEN.contains(&signo) {
|
|
return Err(type_error(format!(
|
|
"Binding to signal '{sig}' is not allowed",
|
|
)));
|
|
}
|
|
|
|
let signal = AsyncRefCell::new(signal(SignalKind::from_raw(signo))?);
|
|
|
|
let (enable_default_handler, has_default_handler) = state
|
|
.borrow_mut::<SignalState>()
|
|
.disable_default_handler(signo);
|
|
|
|
let resource = SignalStreamResource {
|
|
signal,
|
|
cancel: Default::default(),
|
|
enable_default_handler: enable_default_handler.clone(),
|
|
};
|
|
let rid = state.resource_table.add(resource);
|
|
|
|
if !has_default_handler {
|
|
// restore default signal handler when the signal is unbound
|
|
// this can error if the signal is not supported, if so let's just leave it as is
|
|
let _ = signal_hook::flag::register_conditional_default(
|
|
signo,
|
|
enable_default_handler,
|
|
);
|
|
}
|
|
|
|
Ok(rid)
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
#[op2(fast)]
|
|
#[smi]
|
|
fn op_signal_bind(
|
|
state: &mut OpState,
|
|
#[string] sig: &str,
|
|
) -> Result<ResourceId, AnyError> {
|
|
let signo = signal_str_to_int(sig)?;
|
|
let resource = SignalStreamResource {
|
|
signal: AsyncRefCell::new(match signo {
|
|
// SIGINT
|
|
2 => ctrl_c()
|
|
.expect("There was an issue creating ctrl+c event stream.")
|
|
.into(),
|
|
// SIGBREAK
|
|
21 => ctrl_break()
|
|
.expect("There was an issue creating ctrl+break event stream.")
|
|
.into(),
|
|
_ => unimplemented!(),
|
|
}),
|
|
cancel: Default::default(),
|
|
};
|
|
let rid = state.resource_table.add(resource);
|
|
Ok(rid)
|
|
}
|
|
|
|
#[op2(async)]
|
|
async fn op_signal_poll(
|
|
state: Rc<RefCell<OpState>>,
|
|
#[smi] rid: ResourceId,
|
|
) -> Result<bool, AnyError> {
|
|
let resource = state
|
|
.borrow_mut()
|
|
.resource_table
|
|
.get::<SignalStreamResource>(rid)?;
|
|
|
|
let cancel = RcRef::map(&resource, |r| &r.cancel);
|
|
let mut signal = RcRef::map(&resource, |r| &r.signal).borrow_mut().await;
|
|
|
|
match signal.recv().or_cancel(cancel).await {
|
|
Ok(result) => Ok(result.is_none()),
|
|
Err(_) => Ok(true),
|
|
}
|
|
}
|
|
|
|
#[op2(fast)]
|
|
pub fn op_signal_unbind(
|
|
state: &mut OpState,
|
|
#[smi] rid: ResourceId,
|
|
) -> Result<(), AnyError> {
|
|
let resource = state.resource_table.take::<SignalStreamResource>(rid)?;
|
|
|
|
#[cfg(unix)]
|
|
{
|
|
resource
|
|
.enable_default_handler
|
|
.store(true, std::sync::atomic::Ordering::Release);
|
|
}
|
|
|
|
resource.close();
|
|
Ok(())
|
|
}
|