summaryrefslogtreecommitdiff
path: root/runtime/ops/process.rs
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/ops/process.rs')
-rw-r--r--runtime/ops/process.rs40
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::*;