diff options
author | Geert-Jan Zwiers <geertjanzwiers@protonmail.com> | 2022-06-13 22:39:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-13 22:39:46 +0200 |
commit | 24571a395203aad7cda07ffef0ef64285351e42b (patch) | |
tree | 8c003bb92614193b7fc4383936a820954d2c8293 /runtime/ops/signal.rs | |
parent | 21dfeea3c48cf6101d71b39a1d2b0f9406818300 (diff) |
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>
Diffstat (limited to 'runtime/ops/signal.rs')
-rw-r--r-- | runtime/ops/signal.rs | 144 |
1 files changed, 105 insertions, 39 deletions
diff --git a/runtime/ops/signal.rs b/runtime/ops/signal.rs index 72e402094..95c166787 100644 --- a/runtime/ops/signal.rs +++ b/runtime/ops/signal.rs @@ -1,35 +1,24 @@ // 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::AnyError; use deno_core::op; - -use deno_core::Extension; -#[cfg(unix)] -use deno_core::OpState; -#[cfg(unix)] -use std::cell::RefCell; -#[cfg(unix)] -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::Extension; +use deno_core::OpState; use deno_core::RcRef; -#[cfg(unix)] use deno_core::Resource; -#[cfg(unix)] use deno_core::ResourceId; -#[cfg(unix)] + use std::borrow::Cow; +use std::cell::RefCell; +use std::rc::Rc; + #[cfg(unix)] use tokio::signal::unix::{signal, Signal, SignalKind}; +#[cfg(windows)] +use tokio::signal::windows::{ctrl_break, ctrl_c, CtrlBreak, CtrlC}; pub fn init() -> Extension { 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")] pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, AnyError> { 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)] #[op] fn op_signal_bind( @@ -410,7 +470,31 @@ fn op_signal_bind( 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] async fn op_signal_poll( state: Rc<RefCell<OpState>>, @@ -420,6 +504,7 @@ async fn op_signal_poll( .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; @@ -429,7 +514,6 @@ async fn op_signal_poll( } } -#[cfg(unix)] #[op] pub fn op_signal_unbind( state: &mut OpState, @@ -438,21 +522,3 @@ pub fn op_signal_unbind( state.resource_table.close(rid)?; 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")) -} |