From 791d171cd6ff1335581b30c31d9da15b324070dc Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Wed, 10 Jun 2020 09:44:32 -0500 Subject: [PATCH] Remove the rust _subprocess module --- Cargo.lock | 11 -- vm/Cargo.toml | 1 - vm/src/stdlib/mod.rs | 3 - vm/src/stdlib/subprocess.rs | 295 ------------------------------------ 4 files changed, 310 deletions(-) delete mode 100644 vm/src/stdlib/subprocess.rs diff --git a/Cargo.lock b/Cargo.lock index 6eb6018c7..8bada4bad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,7 +1691,6 @@ dependencies = [ "smallbox", "socket2", "statrs", - "subprocess", "thread_local", "uname", "unic-bidi", @@ -1959,16 +1958,6 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" -[[package]] -name = "subprocess" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5109e3c3215ce5339ca9766a6db7f39144ccc7d9bad53b96d65cfb14ae6c2985" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "subtle" version = "1.0.0" diff --git a/vm/Cargo.toml b/vm/Cargo.toml index c212aa7f6..7c0b3c03d 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -101,7 +101,6 @@ uname = "0.1.1" crc32fast = "1.2.0" adler32 = "1.0.3" gethostname = "0.2.0" -subprocess = "0.2.2" socket2 = "0.3" rustyline = "6.0" openssl = { version = "0.10", features = ["vendored"], optional = true } diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index 0ce16fbc0..37515c756 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -59,8 +59,6 @@ mod select; pub mod signal; #[cfg(all(not(target_arch = "wasm32"), feature = "ssl"))] mod ssl; -#[cfg(not(target_arch = "wasm32"))] -mod subprocess; #[cfg(windows)] mod winapi; #[cfg(windows)] @@ -131,7 +129,6 @@ pub fn get_module_inits() -> HashMap { modules.insert("select".to_owned(), Box::new(select::make_module)); #[cfg(feature = "ssl")] modules.insert("_ssl".to_owned(), Box::new(ssl::make_module)); - modules.insert("_subprocess".to_owned(), Box::new(subprocess::make_module)); modules.insert("_thread".to_owned(), Box::new(thread::make_module)); #[cfg(not(target_os = "redox"))] modules.insert("zlib".to_owned(), Box::new(zlib::make_module)); diff --git a/vm/src/stdlib/subprocess.rs b/vm/src/stdlib/subprocess.rs deleted file mode 100644 index 96714398c..000000000 --- a/vm/src/stdlib/subprocess.rs +++ /dev/null @@ -1,295 +0,0 @@ -use std::ffi::OsString; -use std::fs::File; -use std::io::ErrorKind; -use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -use std::time::Duration; - -use crate::function::OptionalArg; -use crate::obj::objbytes::PyBytesRef; -use crate::obj::objlist::PyListRef; -use crate::obj::objstr::{self, PyStringRef}; -use crate::obj::objtype::PyClassRef; -use crate::pyobject::{Either, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue}; -use crate::stdlib::io::io_open; -use crate::stdlib::os::{convert_io_error, raw_file_number, rust_file}; -use crate::vm::VirtualMachine; - -#[derive(Debug)] -struct Popen { - process: RwLock, - args: PyObjectRef, -} - -// Remove once https://github.com/hniksic/rust-subprocess/issues/42 is resolved -#[cfg(windows)] -unsafe impl Sync for Popen {} - -impl PyValue for Popen { - fn class(vm: &VirtualMachine) -> PyClassRef { - vm.class("_subprocess", "Popen") - } -} - -type PopenRef = PyRef; - -#[derive(FromArgs)] -#[allow(dead_code)] -struct PopenArgs { - #[pyarg(positional_only)] - args: Either, - #[pyarg(positional_or_keyword, default = "None")] - stdin: Option, - #[pyarg(positional_or_keyword, default = "None")] - stdout: Option, - #[pyarg(positional_or_keyword, default = "None")] - stderr: Option, - #[pyarg(positional_or_keyword, default = "None")] - close_fds: Option, // TODO: use these unused options - #[pyarg(positional_or_keyword, default = "None")] - cwd: Option, - #[pyarg(positional_or_keyword, default = "None")] - start_new_session: Option, -} - -#[derive(FromArgs)] -struct PopenWaitArgs { - #[pyarg(positional_or_keyword, default = "None")] - timeout: Option, -} - -impl IntoPyObject for subprocess::ExitStatus { - fn into_pyobject(self, vm: &VirtualMachine) -> PyResult { - let status: i32 = match self { - subprocess::ExitStatus::Exited(status) => status as i32, - subprocess::ExitStatus::Signaled(status) => -i32::from(status), - subprocess::ExitStatus::Other(status) => status as i32, - _ => return Err(vm.new_os_error("Unknown exist status".to_owned())), - }; - Ok(vm.new_int(status)) - } -} - -#[cfg(windows)] -const NULL_DEVICE: &str = "nul"; -#[cfg(unix)] -const NULL_DEVICE: &str = "/dev/null"; - -fn convert_redirection(arg: Option, vm: &VirtualMachine) -> PyResult { - match arg { - Some(fd) => match fd { - -1 => Ok(subprocess::Redirection::Pipe), - -2 => Ok(subprocess::Redirection::Merge), - -3 => Ok(subprocess::Redirection::File( - File::open(NULL_DEVICE).unwrap(), - )), - fd => { - if fd < 0 { - Err(vm.new_value_error(format!("Invalid fd: {}", fd))) - } else { - Ok(subprocess::Redirection::File(rust_file(fd))) - } - } - }, - None => Ok(subprocess::Redirection::None), - } -} - -fn convert_to_file_io(file: &Option, mode: &str, vm: &VirtualMachine) -> PyResult { - match file { - Some(ref stdin) => io_open( - vm.new_int(raw_file_number(stdin.try_clone().unwrap())), - Some(mode), - Default::default(), - vm, - ), - None => Ok(vm.get_none()), - } -} - -impl PopenRef { - fn borrow_process(&self) -> RwLockReadGuard<'_, subprocess::Popen> { - self.process.read().unwrap() - } - - fn borrow_process_mut(&self) -> RwLockWriteGuard<'_, subprocess::Popen> { - self.process.write().unwrap() - } - - fn new(cls: PyClassRef, args: PopenArgs, vm: &VirtualMachine) -> PyResult { - let stdin = convert_redirection(args.stdin, vm)?; - let stdout = convert_redirection(args.stdout, vm)?; - let stderr = convert_redirection(args.stderr, vm)?; - let command_list = match &args.args { - Either::A(command) => vec![command.as_str().to_owned()], - Either::B(command_list) => command_list - .borrow_elements() - .iter() - .map(|x| objstr::clone_value(x)) - .collect(), - }; - let cwd = args.cwd.map(|x| OsString::from(x.as_str())); - - let process = subprocess::Popen::create( - &command_list, - subprocess::PopenConfig { - stdin, - stdout, - stderr, - cwd, - ..Default::default() - }, - ) - .map_err(|s| vm.new_os_error(format!("Could not start program: {}", s)))?; - - Popen { - process: RwLock::new(process), - args: args.args.into_object(), - } - .into_ref_with_type(vm, cls) - } - - fn poll(self) -> Option { - self.borrow_process_mut().poll() - } - - fn return_code(self) -> Option { - self.borrow_process().exit_status() - } - - fn wait(self, args: PopenWaitArgs, vm: &VirtualMachine) -> PyResult { - let timeout = match args.timeout { - Some(timeout) => self - .borrow_process_mut() - .wait_timeout(Duration::new(timeout, 0)), - None => self.borrow_process_mut().wait().map(Some), - } - .map_err(|s| vm.new_os_error(format!("Could not start program: {}", s)))?; - if let Some(exit) = timeout { - use subprocess::ExitStatus::*; - Ok(match exit { - Exited(i) => i.into(), - Signaled(s) => -i64::from(s), - _ => unreachable!("should not occur in normal operation"), - }) - } else { - let timeout_expired = vm.try_class("_subprocess", "TimeoutExpired")?; - Err(vm.new_exception_msg(timeout_expired, "Timeout".to_owned())) - } - } - - fn stdin(self, vm: &VirtualMachine) -> PyResult { - convert_to_file_io(&self.borrow_process().stdin, "wb", vm) - } - - fn stdout(self, vm: &VirtualMachine) -> PyResult { - convert_to_file_io(&self.borrow_process().stdout, "rb", vm) - } - - fn stderr(self, vm: &VirtualMachine) -> PyResult { - convert_to_file_io(&self.borrow_process().stderr, "rb", vm) - } - - fn terminate(self, vm: &VirtualMachine) -> PyResult<()> { - self.borrow_process_mut() - .terminate() - .map_err(|err| convert_io_error(vm, err)) - } - - fn kill(self, vm: &VirtualMachine) -> PyResult<()> { - self.borrow_process_mut() - .kill() - .map_err(|err| convert_io_error(vm, err)) - } - - #[allow(clippy::type_complexity)] - fn communicate( - self, - args: PopenCommunicateArgs, - vm: &VirtualMachine, - ) -> PyResult<(Option>, Option>)> { - let bytes = match args.input { - OptionalArg::Present(ref bytes) => Some(bytes.get_value().to_vec()), - OptionalArg::Missing => None, - }; - let mut communicator = self.borrow_process_mut().communicate_start(bytes); - if let OptionalArg::Present(timeout) = args.timeout { - communicator = communicator.limit_time(Duration::new(timeout, 0)); - } - communicator.read().map_err(|err| { - if err.error.kind() == ErrorKind::TimedOut { - let timeout_expired = vm.try_class("_subprocess", "TimeoutExpired").unwrap(); - vm.new_exception_msg(timeout_expired, "Timeout".to_owned()) - } else { - convert_io_error(vm, err.error) - } - }) - } - - fn pid(self) -> Option { - self.borrow_process().pid() - } - - fn enter(self) -> Self { - self - } - - fn exit( - self, - _exception_type: PyObjectRef, - _exception_value: PyObjectRef, - _traceback: PyObjectRef, - ) { - let mut process = self.borrow_process_mut(); - process.stdout.take(); - process.stdin.take(); - process.stderr.take(); - } - - fn args(self) -> PyObjectRef { - self.args.clone() - } -} - -#[derive(FromArgs)] -#[allow(dead_code)] -struct PopenCommunicateArgs { - #[pyarg(positional_or_keyword, optional = true)] - input: OptionalArg, - #[pyarg(positional_or_keyword, optional = true)] - timeout: OptionalArg, -} - -pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { - let ctx = &vm.ctx; - - let subprocess_error = ctx.new_class("SubprocessError", ctx.exceptions.exception_type.clone()); - let timeout_expired = ctx.new_class("TimeoutExpired", subprocess_error.clone()); - let called_process_error = ctx.new_class("CalledProcessError", subprocess_error.clone()); - - let popen = py_class!(ctx, "Popen", ctx.object(), { - (slot new) => PopenRef::new, - "poll" => ctx.new_method(PopenRef::poll), - "returncode" => ctx.new_readonly_getset("returncode", PopenRef::return_code), - "wait" => ctx.new_method(PopenRef::wait), - "stdin" => ctx.new_readonly_getset("stdin", PopenRef::stdin), - "stdout" => ctx.new_readonly_getset("stdout", PopenRef::stdout), - "stderr" => ctx.new_readonly_getset("stderr", PopenRef::stderr), - "terminate" => ctx.new_method(PopenRef::terminate), - "kill" => ctx.new_method(PopenRef::kill), - "communicate" => ctx.new_method(PopenRef::communicate), - "pid" => ctx.new_readonly_getset("pid", PopenRef::pid), - "__enter__" => ctx.new_method(PopenRef::enter), - "__exit__" => ctx.new_method(PopenRef::exit), - "args" => ctx.new_readonly_getset("args", PopenRef::args), - }); - - py_module!(vm, "_subprocess", { - "Popen" => popen, - "SubprocessError" => subprocess_error, - "TimeoutExpired" => timeout_expired, - "CalledProcessError" => called_process_error, - "PIPE" => ctx.new_int(-1), - "STDOUT" => ctx.new_int(-2), - "DEVNULL" => ctx.new_int(-3), - }) -}