diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-12-13 19:45:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-13 19:45:53 +0100 |
commit | 2e74f164b6dcf0ecbf8dd38fba9fae550d784bd0 (patch) | |
tree | 61abe8e09d5331ace5d9de529f0e2737a8e05dbb /cli/ops/process.rs | |
parent | 84ef9bd21fb48fb6b5fbc8dafc3de9f361bade3b (diff) |
refactor: deno_runtime crate (#8640)
This commit moves Deno JS runtime, ops, permissions and
inspector implementation to new "deno_runtime" crate located
in "runtime/" directory.
Details in "runtime/README.md".
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
Diffstat (limited to 'cli/ops/process.rs')
-rw-r--r-- | cli/ops/process.rs | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/cli/ops/process.rs b/cli/ops/process.rs deleted file mode 100644 index 60a6d5095..000000000 --- a/cli/ops/process.rs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. - -use super::io::{std_file_resource, StreamResource, StreamResourceHolder}; -use crate::permissions::Permissions; -use crate::signal::kill; -use deno_core::error::bad_resource_id; -use deno_core::error::type_error; -use deno_core::error::AnyError; -use deno_core::futures::future::poll_fn; -use deno_core::futures::future::FutureExt; -use deno_core::serde_json; -use deno_core::serde_json::json; -use deno_core::serde_json::Value; -use deno_core::BufVec; -use deno_core::OpState; -use deno_core::ZeroCopyBuf; -use serde::Deserialize; -use std::cell::RefCell; -use std::rc::Rc; -use tokio::process::Command; - -#[cfg(unix)] -use std::os::unix::process::ExitStatusExt; - -pub fn init(rt: &mut deno_core::JsRuntime) { - super::reg_json_sync(rt, "op_run", op_run); - super::reg_json_async(rt, "op_run_status", op_run_status); - super::reg_json_sync(rt, "op_kill", op_kill); -} - -fn clone_file( - state: &mut OpState, - rid: u32, -) -> Result<std::fs::File, AnyError> { - std_file_resource(state, rid, move |r| match r { - Ok(std_file) => std_file.try_clone().map_err(AnyError::from), - Err(_) => Err(bad_resource_id()), - }) -} - -fn subprocess_stdio_map(s: &str) -> Result<std::process::Stdio, AnyError> { - match s { - "inherit" => Ok(std::process::Stdio::inherit()), - "piped" => Ok(std::process::Stdio::piped()), - "null" => Ok(std::process::Stdio::null()), - _ => Err(type_error("Invalid resource for stdio")), - } -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct RunArgs { - cmd: Vec<String>, - cwd: Option<String>, - env: Vec<(String, String)>, - stdin: String, - stdout: String, - stderr: String, - stdin_rid: u32, - stdout_rid: u32, - stderr_rid: u32, -} - -struct ChildResource { - child: tokio::process::Child, -} - -fn op_run( - state: &mut OpState, - args: Value, - _zero_copy: &mut [ZeroCopyBuf], -) -> Result<Value, AnyError> { - let run_args: RunArgs = serde_json::from_value(args)?; - state.borrow::<Permissions>().check_run()?; - - let args = run_args.cmd; - let env = run_args.env; - let cwd = run_args.cwd; - - let mut c = Command::new(args.get(0).unwrap()); - (1..args.len()).for_each(|i| { - let arg = args.get(i).unwrap(); - c.arg(arg); - }); - cwd.map(|d| c.current_dir(d)); - for (key, value) in &env { - c.env(key, value); - } - - // TODO: make this work with other resources, eg. sockets - if !run_args.stdin.is_empty() { - c.stdin(subprocess_stdio_map(run_args.stdin.as_ref())?); - } else { - let file = clone_file(state, run_args.stdin_rid)?; - c.stdin(file); - } - - if !run_args.stdout.is_empty() { - c.stdout(subprocess_stdio_map(run_args.stdout.as_ref())?); - } else { - let file = clone_file(state, run_args.stdout_rid)?; - c.stdout(file); - } - - if !run_args.stderr.is_empty() { - c.stderr(subprocess_stdio_map(run_args.stderr.as_ref())?); - } else { - let file = clone_file(state, run_args.stderr_rid)?; - c.stderr(file); - } - - // We want to kill child when it's closed - c.kill_on_drop(true); - - // Spawn the command. - let mut child = c.spawn()?; - let pid = child.id(); - - let stdin_rid = match child.stdin.take() { - Some(child_stdin) => { - let rid = state.resource_table.add( - "childStdin", - Box::new(StreamResourceHolder::new(StreamResource::ChildStdin( - child_stdin, - ))), - ); - Some(rid) - } - None => None, - }; - - let stdout_rid = match child.stdout.take() { - Some(child_stdout) => { - let rid = state.resource_table.add( - "childStdout", - Box::new(StreamResourceHolder::new(StreamResource::ChildStdout( - child_stdout, - ))), - ); - Some(rid) - } - None => None, - }; - - let stderr_rid = match child.stderr.take() { - Some(child_stderr) => { - let rid = state.resource_table.add( - "childStderr", - Box::new(StreamResourceHolder::new(StreamResource::ChildStderr( - child_stderr, - ))), - ); - Some(rid) - } - None => None, - }; - - let child_resource = ChildResource { child }; - let child_rid = state.resource_table.add("child", Box::new(child_resource)); - - Ok(json!({ - "rid": child_rid, - "pid": pid, - "stdinRid": stdin_rid, - "stdoutRid": stdout_rid, - "stderrRid": stderr_rid, - })) -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct RunStatusArgs { - rid: i32, -} - -async fn op_run_status( - state: Rc<RefCell<OpState>>, - args: Value, - _zero_copy: BufVec, -) -> Result<Value, AnyError> { - let args: RunStatusArgs = serde_json::from_value(args)?; - let rid = args.rid as u32; - - { - let s = state.borrow(); - s.borrow::<Permissions>().check_run()?; - } - - let run_status = poll_fn(|cx| { - let mut state = state.borrow_mut(); - let child_resource = state - .resource_table - .get_mut::<ChildResource>(rid) - .ok_or_else(bad_resource_id)?; - let child = &mut child_resource.child; - child.poll_unpin(cx).map_err(AnyError::from) - }) - .await?; - - let code = run_status.code(); - - #[cfg(unix)] - let signal = run_status.signal(); - #[cfg(not(unix))] - let signal = None; - - code - .or(signal) - .expect("Should have either an exit code or a signal."); - let got_signal = signal.is_some(); - - Ok(json!({ - "gotSignal": got_signal, - "exitCode": code.unwrap_or(-1), - "exitSignal": signal.unwrap_or(-1), - })) -} - -#[derive(Deserialize)] -struct KillArgs { - pid: i32, - signo: i32, -} - -fn op_kill( - state: &mut OpState, - args: Value, - _zero_copy: &mut [ZeroCopyBuf], -) -> Result<Value, AnyError> { - super::check_unstable(state, "Deno.kill"); - state.borrow::<Permissions>().check_run()?; - - let args: KillArgs = serde_json::from_value(args)?; - kill(args.pid, args.signo)?; - Ok(json!({})) -} |