diff options
author | Nayeem Rahman <nayeemrmn99@gmail.com> | 2023-05-11 13:53:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-11 14:53:45 +0200 |
commit | 2ba9ccc1ab25e5c631afcbb12b53f4545ca7f750 (patch) | |
tree | 38edbbacb6682b178e0356bf38fbb1f91cc5fe93 /runtime | |
parent | 20c42286f88d861192f35d272a645d8ab6f15be8 (diff) |
fix(runtime): `ChildProcess::kill()` doesn't require additional perms (#15339)
Fixes #15217.
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/js/40_process.js | 7 | ||||
-rw-r--r-- | runtime/ops/process.rs | 40 |
2 files changed, 34 insertions, 13 deletions
diff --git a/runtime/js/40_process.js b/runtime/js/40_process.js index 2a5ac86bf..664a4b303 100644 --- a/runtime/js/40_process.js +++ b/runtime/js/40_process.js @@ -200,6 +200,7 @@ function collectOutput(readableStream) { class ChildProcess { #rid; #waitPromiseId; + #waitComplete = false; #unrefed = false; #pid; @@ -268,8 +269,8 @@ class ChildProcess { const waitPromise = core.opAsync("op_spawn_wait", this.#rid); this.#waitPromiseId = waitPromise[promiseIdSymbol]; this.#status = PromisePrototypeThen(waitPromise, (res) => { - this.#rid = null; signal?.[abortSignal.remove](onAbort); + this.#waitComplete = true; return res; }); } @@ -317,10 +318,10 @@ class ChildProcess { } kill(signo = "SIGTERM") { - if (this.#rid === null) { + if (this.#waitComplete) { throw new TypeError("Child process has already terminated."); } - ops.op_kill(this.#pid, signo, "Deno.Child.kill()"); + ops.op_spawn_kill(this.#rid, signo); } ref() { diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index d991c961f..76db23d02 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -2,6 +2,7 @@ use super::check_unstable; use crate::permissions::PermissionsContainer; +use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; use deno_core::serde_json; @@ -106,6 +107,7 @@ deno_core::extension!( op_spawn_child, op_spawn_wait, op_spawn_sync, + op_spawn_kill, deprecated::op_run, deprecated::op_run_status, deprecated::op_kill, @@ -115,7 +117,9 @@ deno_core::extension!( }, ); -struct ChildResource(tokio::process::Child); +/// Second member stores the pid separately from the RefCell. It's needed for +/// `op_spawn_kill`, where the RefCell is borrowed mutably by `op_spawn_wait`. +struct ChildResource(RefCell<tokio::process::Child>, u32); impl Resource for ChildResource { fn name(&self) -> Cow<str> { @@ -302,7 +306,9 @@ fn spawn_child( .take() .map(|stderr| state.resource_table.add(ChildStderrResource::from(stderr))); - let child_rid = state.resource_table.add(ChildResource(child)); + let child_rid = state + .resource_table + .add(ChildResource(RefCell::new(child), pid)); Ok(Child { rid: child_rid, @@ -328,17 +334,18 @@ async fn op_spawn_wait( state: Rc<RefCell<OpState>>, rid: ResourceId, ) -> Result<ChildStatus, AnyError> { + #![allow(clippy::await_holding_refcell_ref)] let resource = state .borrow_mut() .resource_table - .take::<ChildResource>(rid)?; - Rc::try_unwrap(resource) - .ok() - .unwrap() - .0 - .wait() - .await? - .try_into() + .get::<ChildResource>(rid)?; + let result = resource.0.try_borrow_mut()?.wait().await?.try_into(); + state + .borrow_mut() + .resource_table + .close(rid) + .expect("shouldn't have closed until now"); + result } #[op] @@ -366,6 +373,19 @@ fn op_spawn_sync( }) } +#[op] +fn op_spawn_kill( + state: &mut OpState, + rid: ResourceId, + signal: String, +) -> Result<(), AnyError> { + if let Ok(child_resource) = state.resource_table.get::<ChildResource>(rid) { + deprecated::kill(child_resource.1 as i32, &signal)?; + return Ok(()); + } + Err(type_error("Child process has already terminated.")) +} + mod deprecated { use super::*; |