From 0207ccaf3dc6bcfe5ef46e22c7f8957c9256cb09 Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Mon, 19 Oct 2020 20:39:34 +0200 Subject: [PATCH] Cleanup script-var-handler behaviour --- Cargo.toml | 1 - rustfmt.toml | 2 +- src/script_var_handler.rs | 70 ++++++++++++++++++------------- src/widgets/widget_definitions.rs | 2 +- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 54194ac..0bb7104 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,5 @@ libc = "0.2" ref-cast = "1.0" popol = "0.3" - [dev-dependencies] pretty_assertions = "0.6.1" diff --git a/rustfmt.toml b/rustfmt.toml index a989f2b..c4a051a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -5,7 +5,7 @@ reorder_impl_items = true merge_imports = true normalize_comments = true use_field_init_shorthand = true -wrap_comments = true +#wrap_comments = true combine_control_expr = false condense_wildcard_suffixes = true format_code_in_doc_comments = true diff --git a/src/script_var_handler.rs b/src/script_var_handler.rs index 0196cf1..52ffb2d 100644 --- a/src/script_var_handler.rs +++ b/src/script_var_handler.rs @@ -1,15 +1,13 @@ use std::{ collections::HashMap, io::BufReader, - process::{ChildStdout, Stdio}, + process::{Child, Stdio}, time::Duration, }; -use crate::{ - app, config, eww_state, - value::{PrimitiveValue, VarName}, -}; +use crate::{app, config, eww_state, util, value::PrimitiveValue}; use anyhow::*; +use app::EwwCommand; use glib; use itertools::Itertools; use scheduled_executor; @@ -17,14 +15,14 @@ use std::io::BufRead; /// Handler that manages running and updating [ScriptVar]s pub struct ScriptVarHandler { - evt_send: glib::Sender, + evt_send: glib::Sender, pub poll_handles: Vec, pub poll_executor: scheduled_executor::CoreExecutor, pub tail_handler_thread: Option>, } impl ScriptVarHandler { - pub fn new(evt_send: glib::Sender) -> Result { + pub fn new(evt_send: glib::Sender) -> Result { log::info!("initializing handler for poll script vars"); Ok(ScriptVarHandler { evt_send, @@ -73,11 +71,11 @@ impl ScriptVarHandler { Duration::from_secs(0), var.interval, glib::clone!(@strong var, @strong evt_send => move |_| { - let result = eww_state::run_command(&var.command) - .and_then(|output| Ok(evt_send.send(app::EwwCommand::UpdateVar(var.name.clone(), output))?)); - if let Err(e) = result { - eprintln!("Error while running script-var command: {:?}", e); - } + let result: Result<_> = try { + let output = eww_state::run_command(&var.command)?; + evt_send.send(app::EwwCommand::UpdateVar(var.name.clone(), output))?; + }; + util::print_result_err("while running script-var command", &result); }), ) }) @@ -90,13 +88,18 @@ impl ScriptVarHandler { log::info!("initializing handler for tail script vars"); let mut sources = popol::Sources::with_capacity(tail_script_vars.len()); - let mut command_out_readers: HashMap> = tail_script_vars - .iter() - .filter_map(|var| Some((var.name.clone(), try_run_command(&var.command)?))) - .collect(); + let mut command_children = Vec::new(); + let mut command_out_handles = HashMap::new(); - for (var_name, reader) in command_out_readers.iter() { - sources.register(var_name.clone(), reader.get_ref(), popol::interest::READ); + for var in tail_script_vars { + if let Some(mut child) = try_run_command(&var.command) { + command_out_handles.insert(var.name.clone(), BufReader::new(child.stdout.take().unwrap())); + command_children.push(child); + } + } + + for (var_name, handle) in command_out_handles.iter() { + sources.register(var_name.clone(), handle.get_ref(), popol::interest::READ); } let mut events = popol::Events::with_capacity(tail_script_vars.len()); @@ -108,24 +111,26 @@ impl ScriptVarHandler { sources.wait(&mut events)?; for (var_name, event) in events.iter() { if event.readable { - let handle = command_out_readers + let handle = command_out_handles .get_mut(var_name) .with_context(|| format!("No command output handle found for variable '{}'", var_name))?; let mut buffer = String::new(); handle.read_line(&mut buffer)?; - evt_send.send(app::EwwCommand::UpdateVar( + evt_send.send(EwwCommand::UpdateVar( var_name.clone(), - PrimitiveValue::from_string(buffer), + PrimitiveValue::from_string(buffer.trim_matches('\n').to_owned()), ))?; } else if event.hangup { - command_out_readers.remove(var_name); + command_out_handles.remove(var_name); } } }; - if let Err(err) = result { - eprintln!("Error in script-var tail handler thread: {:?}", err); - continue; - } + util::print_result_err("in script-var tail handler thread", &result); + } + + // stop child processes after exit + for mut child in command_children { + let _ = child.kill(); } }); self.tail_handler_thread = Some(thread_handle); @@ -133,21 +138,26 @@ impl ScriptVarHandler { } } +impl Drop for ScriptVarHandler { + fn drop(&mut self) { + self.stop(); + } +} + /// Run a command in sh, returning its stdout-handle wrapped in a /// [`BufReader`]. If running the command fails, will print a warning /// and return `None`. -fn try_run_command(command: &str) -> Option> { +fn try_run_command(command: &str) -> Option { let result = std::process::Command::new("sh") .arg("-c") .arg(command) .stdout(Stdio::piped()) .stderr(Stdio::inherit()) .stdin(Stdio::null()) - .spawn() - .map(|mut x| x.stdout.take().unwrap()); + .spawn(); match result { - Ok(stdout) => Some(BufReader::new(stdout)), + Ok(handle) => Some(handle), Err(err) => { eprintln!("WARN: Error running command from script-variable: {:?}", err); None diff --git a/src/widgets/widget_definitions.rs b/src/widgets/widget_definitions.rs index 6ba577f..f7f3bb6 100644 --- a/src/widgets/widget_definitions.rs +++ b/src/widgets/widget_definitions.rs @@ -237,7 +237,7 @@ fn build_gtk_label(bargs: &mut BuilderArgs) -> Result { let gtk_widget = gtk::Label::new(None); resolve_block!(bargs, gtk_widget, { // @prop - the text to display - prop(text: as_string) { gtk_widget.set_text(dbg!(&text)) }, + prop(text: as_string) { gtk_widget.set_text(&text) }, }); Ok(gtk_widget) }