diff options
Diffstat (limited to 'runtime/ops/process.rs')
-rw-r--r-- | runtime/ops/process.rs | 54 |
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 + ))) } } |