summaryrefslogtreecommitdiff
path: root/runtime/ops/process.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/process.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/process.rs')
-rw-r--r--runtime/ops/process.rs54
1 files changed, 45 insertions, 9 deletions
diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs
index ab303e210..bd6328ae9 100644
--- a/runtime/ops/process.rs
+++ b/runtime/ops/process.rs
@@ -301,7 +301,6 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
use deno_core::error::type_error;
use std::io::Error;
use std::io::ErrorKind::NotFound;
- use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::FALSE;
use winapi::shared::minwindef::TRUE;
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::processthreadsapi::OpenProcess;
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;
- if !matches!(signal, "SIGKILL" | "SIGTERM") {
- Err(type_error(format!("Invalid signal: {}", signal)))
- } else if pid <= 0 {
- Err(type_error("Invalid pid"))
- } else {
- let handle = unsafe { OpenProcess(PROCESS_TERMINATE, FALSE, pid as DWORD) };
+ if pid < 0 {
+ return Err(type_error(format!(
+ "Invalid process id (pid) {} for signal {}.",
+ pid, signal
+ )));
+ }
+
+ 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() {
let err = match unsafe { GetLastError() } {
ERROR_INVALID_PARAMETER => Error::from(NotFound), // Invalid `pid`.
@@ -324,14 +355,19 @@ pub fn kill(pid: i32, signal: &str) -> Result<(), AnyError> {
};
Err(err.into())
} else {
- let r = unsafe { TerminateProcess(handle, 1) };
+ let is_terminated = unsafe { TerminateProcess(handle, 1) };
unsafe { CloseHandle(handle) };
- match r {
+ match is_terminated {
FALSE => Err(Error::last_os_error().into()),
TRUE => Ok(()),
_ => unreachable!(),
}
}
+ } else {
+ Err(type_error(format!(
+ "Signal {} is unsupported on Windows.",
+ signal
+ )))
}
}