diff options
Diffstat (limited to 'runtime/ops/process.rs')
-rw-r--r-- | runtime/ops/process.rs | 40 |
1 files changed, 30 insertions, 10 deletions
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::*; |