From 96fedb47eebbc287c7c7e842b853b3b12520f80c Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Mon, 31 Jan 2022 10:20:11 -0500 Subject: [PATCH] Wait on the plugin child to prevent zombies (#901) --- crates/nu-plugin/src/plugin/declaration.rs | 35 +++++++++++----------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/crates/nu-plugin/src/plugin/declaration.rs b/crates/nu-plugin/src/plugin/declaration.rs index 99a0634efb..e6f3a6f457 100644 --- a/crates/nu-plugin/src/plugin/declaration.rs +++ b/crates/nu-plugin/src/plugin/declaration.rs @@ -92,28 +92,26 @@ impl Command for PluginDeclaration { let reader = stdout_reader; let mut buf_read = BufReader::with_capacity(OUTPUT_BUFFER_SIZE, reader); - let response = self - .encoding - .decode_response(&mut buf_read) - .map_err(|err| { - let decl = engine_state.get_decl(call.decl_id); - ShellError::SpannedLabeledError( - format!("Unable to decode call for {}", decl.name()), - err.to_string(), - call.head, - ) - })?; + let response = self.encoding.decode_response(&mut buf_read).map_err(|err| { + let decl = engine_state.get_decl(call.decl_id); + ShellError::SpannedLabeledError( + format!("Unable to decode call for {}", decl.name()), + err.to_string(), + call.head, + ) + }); match response { - PluginResponse::Value(value) => { + Ok(PluginResponse::Value(value)) => { Ok(PipelineData::Value(value.as_ref().clone(), None)) } - PluginResponse::Error(err) => Err(err.into()), - PluginResponse::Signature(..) => Err(ShellError::SpannedLabeledError( + Ok(PluginResponse::Error(err)) => Err(err.into()), + Ok(PluginResponse::Signature(..)) => Err(ShellError::SpannedLabeledError( "Plugin missing value".into(), "Received a signature from plugin instead of value".into(), call.head, )), + Err(err) => Err(err), } } else { Err(ShellError::SpannedLabeledError( @@ -121,11 +119,12 @@ impl Command for PluginDeclaration { "no stdout reader".into(), call.head, )) - }?; + }; - // There is no need to wait for the child process to finish - // The response has been collected from the plugin call - Ok(pipeline_data) + // We need to call .wait() on the child, or we'll risk summoning the zombie horde + let _ = child.wait(); + + pipeline_data } fn is_plugin(&self) -> Option<(&PathBuf, &str, &Option)> {