mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat(runtime/signal): implement SIGINT and SIGBREAK for windows (#14694)
This commit adds support for SIGINT and SIGBREAK signals on Windows platform. Co-authored-by: orange soeur <juzi201314@gmail.com>
This commit is contained in:
parent
21dfeea3c4
commit
24571a3952
4 changed files with 242 additions and 89 deletions
8
cli/dts/lib.deno.ns.d.ts
vendored
8
cli/dts/lib.deno.ns.d.ts
vendored
|
@ -2342,6 +2342,7 @@ declare namespace Deno {
|
||||||
export type Signal =
|
export type Signal =
|
||||||
| "SIGABRT"
|
| "SIGABRT"
|
||||||
| "SIGALRM"
|
| "SIGALRM"
|
||||||
|
| "SIGBREAK"
|
||||||
| "SIGBUS"
|
| "SIGBUS"
|
||||||
| "SIGCHLD"
|
| "SIGCHLD"
|
||||||
| "SIGCONT"
|
| "SIGCONT"
|
||||||
|
@ -2382,7 +2383,7 @@ declare namespace Deno {
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* NOTE: This functionality is not yet implemented on Windows.
|
* NOTE: On Windows only SIGINT (ctrl+c) and SIGBREAK (ctrl+break) are supported.
|
||||||
*/
|
*/
|
||||||
export function addSignalListener(signal: Signal, handler: () => void): void;
|
export function addSignalListener(signal: Signal, handler: () => void): void;
|
||||||
|
|
||||||
|
@ -2397,7 +2398,7 @@ declare namespace Deno {
|
||||||
* Deno.removeSignalListener("SIGTERM", listener);
|
* Deno.removeSignalListener("SIGTERM", listener);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* NOTE: This functionality is not yet implemented on Windows.
|
* NOTE: On Windows only SIGINT (ctrl+c) and SIGBREAK (ctrl+break) are supported.
|
||||||
*/
|
*/
|
||||||
export function removeSignalListener(
|
export function removeSignalListener(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
|
@ -2937,7 +2938,8 @@ declare namespace Deno {
|
||||||
/** Send a signal to process under given `pid`.
|
/** Send a signal to process under given `pid`.
|
||||||
*
|
*
|
||||||
* If `pid` is negative, the signal will be sent to the process group
|
* If `pid` is negative, the signal will be sent to the process group
|
||||||
* identified by `pid`.
|
* identified by `pid`. An error will be thrown if a negative
|
||||||
|
* `pid` is used on Windows.
|
||||||
*
|
*
|
||||||
* ```ts
|
* ```ts
|
||||||
* const p = Deno.run({
|
* const p = Deno.run({
|
||||||
|
|
|
@ -4,89 +4,102 @@ import { assertEquals, assertThrows, deferred, delay } from "./test_util.ts";
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ ignore: Deno.build.os !== "windows" },
|
{ ignore: Deno.build.os !== "windows" },
|
||||||
function signalsNotImplemented() {
|
function signalsNotImplemented() {
|
||||||
assertThrows(
|
const msg =
|
||||||
() => {
|
"Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK).";
|
||||||
Deno.addSignalListener("SIGINT", () => {});
|
|
||||||
},
|
|
||||||
Error,
|
|
||||||
"not implemented",
|
|
||||||
);
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGALRM", () => {});
|
Deno.addSignalListener("SIGALRM", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGCHLD", () => {});
|
Deno.addSignalListener("SIGCHLD", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGHUP", () => {});
|
Deno.addSignalListener("SIGHUP", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
|
||||||
assertThrows(
|
|
||||||
() => {
|
|
||||||
Deno.addSignalListener("SIGINT", () => {});
|
|
||||||
},
|
|
||||||
Error,
|
|
||||||
"not implemented",
|
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGIO", () => {});
|
Deno.addSignalListener("SIGIO", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGPIPE", () => {});
|
Deno.addSignalListener("SIGPIPE", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGQUIT", () => {});
|
Deno.addSignalListener("SIGQUIT", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGTERM", () => {});
|
Deno.addSignalListener("SIGTERM", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGUSR1", () => {});
|
Deno.addSignalListener("SIGUSR1", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGUSR2", () => {});
|
Deno.addSignalListener("SIGUSR2", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
);
|
);
|
||||||
assertThrows(
|
assertThrows(
|
||||||
() => {
|
() => {
|
||||||
Deno.addSignalListener("SIGWINCH", () => {});
|
Deno.addSignalListener("SIGWINCH", () => {});
|
||||||
},
|
},
|
||||||
Error,
|
Error,
|
||||||
"not implemented",
|
msg,
|
||||||
|
);
|
||||||
|
assertThrows(
|
||||||
|
() => Deno.addSignalListener("SIGKILL", () => {}),
|
||||||
|
Error,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
|
assertThrows(
|
||||||
|
() => Deno.addSignalListener("SIGSTOP", () => {}),
|
||||||
|
Error,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
|
assertThrows(
|
||||||
|
() => Deno.addSignalListener("SIGILL", () => {}),
|
||||||
|
Error,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
|
assertThrows(
|
||||||
|
() => Deno.addSignalListener("SIGFPE", () => {}),
|
||||||
|
Error,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
|
assertThrows(
|
||||||
|
() => Deno.addSignalListener("SIGSEGV", () => {}),
|
||||||
|
Error,
|
||||||
|
msg,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -169,7 +182,6 @@ Deno.test(
|
||||||
// This tests that pending op_signal_poll doesn't block the runtime from exiting the process.
|
// This tests that pending op_signal_poll doesn't block the runtime from exiting the process.
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{
|
{
|
||||||
ignore: Deno.build.os === "windows",
|
|
||||||
permissions: { run: true, read: true },
|
permissions: { run: true, read: true },
|
||||||
},
|
},
|
||||||
async function canExitWhileListeningToSignal() {
|
async function canExitWhileListeningToSignal() {
|
||||||
|
@ -177,7 +189,7 @@ Deno.test(
|
||||||
args: [
|
args: [
|
||||||
"eval",
|
"eval",
|
||||||
"--unstable",
|
"--unstable",
|
||||||
"Deno.addSignalListener('SIGIO', () => {})",
|
"Deno.addSignalListener('SIGINT', () => {})",
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
assertEquals(status.code, 0);
|
assertEquals(status.code, 0);
|
||||||
|
@ -186,21 +198,58 @@ Deno.test(
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{
|
{
|
||||||
ignore: Deno.build.os === "windows",
|
ignore: Deno.build.os !== "windows",
|
||||||
permissions: { run: true },
|
permissions: { run: true },
|
||||||
},
|
},
|
||||||
function signalInvalidHandlerTest() {
|
function windowsThrowsOnNegativeProcessIdTest() {
|
||||||
assertThrows(() => {
|
assertThrows(
|
||||||
// deno-lint-ignore no-explicit-any
|
() => {
|
||||||
Deno.addSignalListener("SIGINT", "handler" as any);
|
Deno.kill(-1, "SIGINT");
|
||||||
});
|
},
|
||||||
assertThrows(() => {
|
TypeError,
|
||||||
// deno-lint-ignore no-explicit-any
|
"Invalid process id (pid) -1 for signal SIGINT.",
|
||||||
Deno.removeSignalListener("SIGINT", "handler" as any);
|
);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{
|
||||||
|
ignore: Deno.build.os !== "windows",
|
||||||
|
permissions: { run: true },
|
||||||
|
},
|
||||||
|
function noOpenSystemIdleProcessTest() {
|
||||||
|
let signal: Deno.Signal = "SIGKILL";
|
||||||
|
|
||||||
|
assertThrows(
|
||||||
|
() => {
|
||||||
|
Deno.kill(0, signal);
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
`Cannot use ${signal} on PID 0`,
|
||||||
|
);
|
||||||
|
|
||||||
|
signal = "SIGTERM";
|
||||||
|
assertThrows(
|
||||||
|
() => {
|
||||||
|
Deno.kill(0, signal);
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
`Cannot use ${signal} on PID 0`,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Deno.test(function signalInvalidHandlerTest() {
|
||||||
|
assertThrows(() => {
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
Deno.addSignalListener("SIGINT", "handler" as any);
|
||||||
|
});
|
||||||
|
assertThrows(() => {
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
Deno.removeSignalListener("SIGINT", "handler" as any);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{
|
{
|
||||||
ignore: Deno.build.os === "windows",
|
ignore: Deno.build.os === "windows",
|
||||||
|
|
|
@ -301,7 +301,6 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::io::ErrorKind::NotFound;
|
use std::io::ErrorKind::NotFound;
|
||||||
use winapi::shared::minwindef::DWORD;
|
|
||||||
use winapi::shared::minwindef::FALSE;
|
use winapi::shared::minwindef::FALSE;
|
||||||
use winapi::shared::minwindef::TRUE;
|
use winapi::shared::minwindef::TRUE;
|
||||||
use winapi::shared::winerror::ERROR_INVALID_PARAMETER;
|
use winapi::shared::winerror::ERROR_INVALID_PARAMETER;
|
||||||
|
@ -309,14 +308,46 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
|
||||||
use winapi::um::handleapi::CloseHandle;
|
use winapi::um::handleapi::CloseHandle;
|
||||||
use winapi::um::processthreadsapi::OpenProcess;
|
use winapi::um::processthreadsapi::OpenProcess;
|
||||||
use winapi::um::processthreadsapi::TerminateProcess;
|
use winapi::um::processthreadsapi::TerminateProcess;
|
||||||
|
use winapi::um::wincon::GenerateConsoleCtrlEvent;
|
||||||
|
use winapi::um::wincon::{CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_C_EVENT};
|
||||||
use winapi::um::winnt::PROCESS_TERMINATE;
|
use winapi::um::winnt::PROCESS_TERMINATE;
|
||||||
|
|
||||||
if !matches!(signal, "SIGKILL" | "SIGTERM") {
|
if pid < 0 {
|
||||||
Err(type_error(format!("Invalid signal: {}", signal)))
|
return Err(type_error(format!(
|
||||||
} else if pid <= 0 {
|
"Invalid process id (pid) {} for signal {}.",
|
||||||
Err(type_error("Invalid pid"))
|
pid, signal
|
||||||
} else {
|
)));
|
||||||
let handle = unsafe { OpenProcess(PROCESS_TERMINATE, FALSE, pid as DWORD) };
|
}
|
||||||
|
|
||||||
|
if matches!(signal, "SIGINT" | "SIGBREAK" | "SIGHUP") {
|
||||||
|
let is_generated = unsafe {
|
||||||
|
GenerateConsoleCtrlEvent(
|
||||||
|
match signal {
|
||||||
|
"SIGINT" => CTRL_C_EVENT,
|
||||||
|
"SIGBREAK" => CTRL_BREAK_EVENT,
|
||||||
|
// Need tokio::windows::signal::CtrlClose or equivalent
|
||||||
|
// in signal.rs to get this working
|
||||||
|
"SIGHUP" => CTRL_CLOSE_EVENT,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
pid as u32,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match is_generated {
|
||||||
|
FALSE => {
|
||||||
|
Err(Error::from_raw_os_error(unsafe { GetLastError() } as i32).into())
|
||||||
|
}
|
||||||
|
TRUE => Ok(()),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
} else if matches!(signal, "SIGKILL" | "SIGTERM") {
|
||||||
|
// PID 0 = System Idle Process and can't be opened.
|
||||||
|
if pid == 0 {
|
||||||
|
return Err(type_error(format!("Cannot use {} on PID 0", signal)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle = unsafe { OpenProcess(PROCESS_TERMINATE, FALSE, pid as u32) };
|
||||||
|
|
||||||
if handle.is_null() {
|
if handle.is_null() {
|
||||||
let err = match unsafe { GetLastError() } {
|
let err = match unsafe { GetLastError() } {
|
||||||
ERROR_INVALID_PARAMETER => Error::from(NotFound), // Invalid `pid`.
|
ERROR_INVALID_PARAMETER => Error::from(NotFound), // Invalid `pid`.
|
||||||
|
@ -324,14 +355,19 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
|
||||||
};
|
};
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
} else {
|
} else {
|
||||||
let r = unsafe { TerminateProcess(handle, 1) };
|
let is_terminated = unsafe { TerminateProcess(handle, 1) };
|
||||||
unsafe { CloseHandle(handle) };
|
unsafe { CloseHandle(handle) };
|
||||||
match r {
|
match is_terminated {
|
||||||
FALSE => Err(Error::last_os_error().into()),
|
FALSE => Err(Error::last_os_error().into()),
|
||||||
TRUE => Ok(()),
|
TRUE => Ok(()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(type_error(format!(
|
||||||
|
"Signal {} is unsupported on Windows.",
|
||||||
|
signal
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,24 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
#[cfg(not(unix))]
|
|
||||||
use deno_core::error::generic_error;
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op;
|
use deno_core::op;
|
||||||
|
use deno_core::AsyncRefCell;
|
||||||
|
use deno_core::CancelFuture;
|
||||||
|
use deno_core::CancelHandle;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
#[cfg(unix)]
|
use deno_core::RcRef;
|
||||||
|
use deno_core::Resource;
|
||||||
|
use deno_core::ResourceId;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
#[cfg(unix)]
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::AsyncRefCell;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::CancelFuture;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::CancelHandle;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::RcRef;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::Resource;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use deno_core::ResourceId;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use std::borrow::Cow;
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use tokio::signal::unix::{signal, Signal, SignalKind};
|
use tokio::signal::unix::{signal, Signal, SignalKind};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use tokio::signal::windows::{ctrl_break, ctrl_c, CtrlBreak, CtrlC};
|
||||||
|
|
||||||
pub fn init() -> Extension {
|
pub fn init() -> Extension {
|
||||||
Extension::builder()
|
Extension::builder()
|
||||||
|
@ -60,6 +49,55 @@ impl Resource for SignalStreamResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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")]
|
#[cfg(target_os = "freebsd")]
|
||||||
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> {
|
||||||
match s {
|
match s {
|
||||||
|
@ -389,6 +427,28 @@ pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, AnyError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[cfg(unix)]
|
||||||
#[op]
|
#[op]
|
||||||
fn op_signal_bind(
|
fn op_signal_bind(
|
||||||
|
@ -410,7 +470,31 @@ fn op_signal_bind(
|
||||||
Ok(rid)
|
Ok(rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(windows)]
|
||||||
|
#[op]
|
||||||
|
fn op_signal_bind(
|
||||||
|
state: &mut OpState,
|
||||||
|
sig: String,
|
||||||
|
) -> 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)
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
async fn op_signal_poll(
|
async fn op_signal_poll(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
@ -420,6 +504,7 @@ async fn op_signal_poll(
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.resource_table
|
.resource_table
|
||||||
.get::<SignalStreamResource>(rid)?;
|
.get::<SignalStreamResource>(rid)?;
|
||||||
|
|
||||||
let cancel = RcRef::map(&resource, |r| &r.cancel);
|
let cancel = RcRef::map(&resource, |r| &r.cancel);
|
||||||
let mut signal = RcRef::map(&resource, |r| &r.signal).borrow_mut().await;
|
let mut signal = RcRef::map(&resource, |r| &r.signal).borrow_mut().await;
|
||||||
|
|
||||||
|
@ -429,7 +514,6 @@ async fn op_signal_poll(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
#[op]
|
#[op]
|
||||||
pub fn op_signal_unbind(
|
pub fn op_signal_unbind(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
@ -438,21 +522,3 @@ pub fn op_signal_unbind(
|
||||||
state.resource_table.close(rid)?;
|
state.resource_table.close(rid)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
#[op]
|
|
||||||
pub fn op_signal_bind() -> Result<(), AnyError> {
|
|
||||||
Err(generic_error("not implemented"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
#[op]
|
|
||||||
fn op_signal_unbind() -> Result<(), AnyError> {
|
|
||||||
Err(generic_error("not implemented"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
#[op]
|
|
||||||
async fn op_signal_poll() -> Result<(), AnyError> {
|
|
||||||
Err(generic_error("not implemented"))
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue