summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-04-20 18:55:07 +0530
committerGitHub <noreply@github.com>2024-04-20 18:55:07 +0530
commitc0f40ed81a1c932f804ba62e635249cd43c31273 (patch)
treea8ce324f17f819eb62fe93199664886b769d9c5f
parent04c6785faecdef37b3d4eefb61c0a18ff1cbdec0 (diff)
fix(ext/node): implement process.kill in Rust (#23130)
Closes https://github.com/denoland/deno/issues/23056
-rw-r--r--Cargo.lock1
-rw-r--r--ext/node/Cargo.toml1
-rw-r--r--ext/node/lib.rs3
-rw-r--r--ext/node/ops/mod.rs1
-rw-r--r--ext/node/ops/os/mod.rs5
-rw-r--r--ext/node/ops/process.rs64
-rw-r--r--ext/node/polyfills/process.ts57
-rw-r--r--tests/unit_node/process_test.ts12
8 files changed, 94 insertions, 50 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c6748e5b4..9f499aa2b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1684,6 +1684,7 @@ dependencies = [
"deno_fs",
"deno_media_type",
"deno_net",
+ "deno_permissions",
"deno_whoami",
"digest",
"dsa",
diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml
index 928968a9e..c4fcbd3ac 100644
--- a/ext/node/Cargo.toml
+++ b/ext/node/Cargo.toml
@@ -26,6 +26,7 @@ deno_fetch.workspace = true
deno_fs.workspace = true
deno_media_type.workspace = true
deno_net.workspace = true
+deno_permissions.workspace = true
deno_whoami = "0.1.0"
digest = { version = "0.10.5", features = ["core-api", "std"] }
dsa = "0.6.1"
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index f91ed0b1a..c99467d23 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -307,7 +307,6 @@ deno_core::extension!(deno_node,
ops::os::op_node_os_username<P>,
ops::os::op_geteuid<P>,
ops::os::op_cpus<P>,
- ops::os::op_process_abort,
op_node_build_os,
op_node_is_promise_rejected,
op_npm_process_state,
@@ -340,6 +339,8 @@ deno_core::extension!(deno_node,
ops::ipc::op_node_child_ipc_pipe,
ops::ipc::op_node_ipc_write,
ops::ipc::op_node_ipc_read,
+ ops::process::op_node_process_kill,
+ ops::process::op_process_abort,
],
esm_entry_point = "ext:deno_node/02_init.js",
esm = [
diff --git a/ext/node/ops/mod.rs b/ext/node/ops/mod.rs
index c14b63bf4..6381530dd 100644
--- a/ext/node/ops/mod.rs
+++ b/ext/node/ops/mod.rs
@@ -7,6 +7,7 @@ pub mod http2;
pub mod idna;
pub mod ipc;
pub mod os;
+pub mod process;
pub mod require;
pub mod util;
pub mod v8;
diff --git a/ext/node/ops/os/mod.rs b/ext/node/ops/os/mod.rs
index 1d3de797b..603f678e0 100644
--- a/ext/node/ops/os/mod.rs
+++ b/ext/node/ops/os/mod.rs
@@ -75,11 +75,6 @@ where
Ok(euid)
}
-#[op2(fast)]
-pub fn op_process_abort() {
- std::process::abort();
-}
-
#[op2]
#[serde]
pub fn op_cpus<P>(state: &mut OpState) -> Result<Vec<cpus::CpuInfo>, AnyError>
diff --git a/ext/node/ops/process.rs b/ext/node/ops/process.rs
new file mode 100644
index 000000000..0992c46c6
--- /dev/null
+++ b/ext/node/ops/process.rs
@@ -0,0 +1,64 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::error::AnyError;
+use deno_core::op2;
+use deno_core::OpState;
+use deno_permissions::PermissionsContainer;
+
+#[cfg(unix)]
+fn kill(pid: i32, sig: i32) -> i32 {
+ // SAFETY: FFI call to libc
+ if unsafe { libc::kill(pid, sig) } < 0 {
+ std::io::Error::last_os_error().raw_os_error().unwrap()
+ } else {
+ 0
+ }
+}
+
+#[cfg(not(unix))]
+fn kill(pid: i32, _sig: i32) -> i32 {
+ use winapi::shared::minwindef::DWORD;
+ use winapi::shared::minwindef::FALSE;
+ use winapi::shared::minwindef::TRUE;
+ use winapi::um::errhandlingapi::GetLastError;
+ use winapi::um::processthreadsapi::GetCurrentProcess;
+ use winapi::um::processthreadsapi::OpenProcess;
+ use winapi::um::processthreadsapi::TerminateProcess;
+ use winapi::um::winnt::PROCESS_TERMINATE;
+
+ // SAFETY: FFI call to winapi
+ unsafe {
+ let p_hnd = if pid == 0 {
+ GetCurrentProcess()
+ } else {
+ OpenProcess(PROCESS_TERMINATE, FALSE, pid as DWORD)
+ };
+
+ if p_hnd.is_null() {
+ return GetLastError() as i32;
+ }
+
+ if TerminateProcess(p_hnd, 1) == TRUE {
+ return 0;
+ }
+
+ GetLastError() as i32
+ }
+}
+
+#[op2(fast)]
+pub fn op_node_process_kill(
+ state: &mut OpState,
+ #[smi] pid: i32,
+ #[smi] sig: i32,
+) -> Result<i32, AnyError> {
+ state
+ .borrow_mut::<PermissionsContainer>()
+ .check_run_all("process.kill")?;
+ Ok(kill(pid, sig))
+}
+
+#[op2(fast)]
+pub fn op_process_abort() {
+ std::process::abort();
+}
diff --git a/ext/node/polyfills/process.ts b/ext/node/polyfills/process.ts
index b89b7af52..7f522386c 100644
--- a/ext/node/polyfills/process.ts
+++ b/ext/node/polyfills/process.ts
@@ -5,9 +5,14 @@
// deno-lint-ignore-file prefer-primordials
import { core, internals } from "ext:core/mod.js";
-import { op_geteuid, op_process_abort, op_set_exit_code } from "ext:core/ops";
+import {
+ op_geteuid,
+ op_node_process_kill,
+ op_process_abort,
+ op_set_exit_code,
+} from "ext:core/ops";
-import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts";
+import { warnNotImplemented } from "ext:deno_node/_utils.ts";
import { EventEmitter } from "node:events";
import Module from "node:module";
import { report } from "ext:deno_node/internal/process/report.ts";
@@ -43,7 +48,6 @@ import {
} from "ext:deno_node/_next_tick.ts";
import { isWindows } from "ext:deno_node/_util/os.ts";
import * as io from "ext:deno_io/12_io.js";
-import { Command } from "ext:runtime/40_process.js";
export let argv0 = "";
@@ -254,49 +258,14 @@ memoryUsage.rss = function (): number {
// Returns a negative error code than can be recognized by errnoException
function _kill(pid: number, sig: number): number {
- let errCode;
-
- if (sig === 0) {
- let status;
- if (Deno.build.os === "windows") {
- status = (new Command("powershell.exe", {
- args: ["Get-Process", "-pid", pid],
- })).outputSync();
- } else {
- status = (new Command("kill", {
- args: ["-0", pid],
- })).outputSync();
- }
-
- if (!status.success) {
- errCode = uv.codeMap.get("ESRCH");
- }
- } else {
- // Reverse search the shortname based on the numeric code
- const maybeSignal = Object.entries(constants.os.signals).find((
- [_, numericCode],
- ) => numericCode === sig);
+ const maybeSignal = Object.entries(constants.os.signals).find((
+ [_, numericCode],
+ ) => numericCode === sig);
- if (!maybeSignal) {
- errCode = uv.codeMap.get("EINVAL");
- } else {
- try {
- Deno.kill(pid, maybeSignal[0] as Deno.Signal);
- } catch (e) {
- if (e instanceof TypeError) {
- throw notImplemented(maybeSignal[0]);
- }
-
- throw e;
- }
- }
- }
-
- if (!errCode) {
- return 0;
- } else {
- return errCode;
+ if (!maybeSignal) {
+ return uv.codeMap.get("EINVAL");
}
+ return op_node_process_kill(pid, sig);
}
export function dlopen(module, filename, _flags) {
diff --git a/tests/unit_node/process_test.ts b/tests/unit_node/process_test.ts
index f32303002..0ae0c2a7a 100644
--- a/tests/unit_node/process_test.ts
+++ b/tests/unit_node/process_test.ts
@@ -235,6 +235,18 @@ Deno.test({
},
});
+Deno.test(
+ { permissions: { run: true, read: true } },
+ async function processKill() {
+ const p = new Deno.Command(Deno.execPath(), {
+ args: ["eval", "setTimeout(() => {}, 10000)"],
+ }).spawn();
+
+ process.kill(p.pid);
+ await p.status;
+ },
+);
+
Deno.test({
name: "process.off signal",
ignore: Deno.build.os == "windows",