summaryrefslogtreecommitdiff
path: root/runtime/ops/signal.rs
diff options
context:
space:
mode:
authorGeert-Jan Zwiers <geertjanzwiers@protonmail.com>2022-06-13 22:39:46 +0200
committerGitHub <noreply@github.com>2022-06-13 22:39:46 +0200
commit24571a395203aad7cda07ffef0ef64285351e42b (patch)
tree8c003bb92614193b7fc4383936a820954d2c8293 /runtime/ops/signal.rs
parent21dfeea3c48cf6101d71b39a1d2b0f9406818300 (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.rs144
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"))
-}