From 5e01fbe066ceb0406180734d1bf82e257846d5bb Mon Sep 17 00:00:00 2001 From: shy Date: Thu, 8 Apr 2021 11:17:06 +0200 Subject: [PATCH] Tend to spawned processes. --- src/alarm.rs | 18 +++++++++--------- src/main.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/alarm.rs b/src/alarm.rs index 5d47ec3..1df3f59 100644 --- a/src/alarm.rs +++ b/src/alarm.rs @@ -1,5 +1,5 @@ use std::io::Write; -use std::process::{Command, Stdio}; +use std::process::{Command, Stdio, Child}; use termion::{color, cursor, style}; use termion::raw::RawTerminal; use crate::{Clock, Config, Layout, Position}; @@ -267,7 +267,7 @@ impl AlarmRoster { } // Execute the command given on the command line. -pub fn alarm_exec(config: &Config, elapsed: u32) { +pub fn alarm_exec(config: &Config, elapsed: u32) -> Option { let mut args: Vec = Vec::new(); let time: String; @@ -283,14 +283,14 @@ pub fn alarm_exec(config: &Config, elapsed: u32) { args.push(s.replace("{}", &time)); } - if Command::new(&exec[0]) - .args(&args[1..]) - .stdout(Stdio::null()) - .stdin(Stdio::null()) - .spawn().is_err() { - - eprintln!("Error: Could not execute command"); + match Command::new(&exec[0]).args(&args[1..]) + .stdout(Stdio::null()).stdin(Stdio::null()).spawn() { + Ok(child) => return Some(child), + Err(error) => { + eprintln!("Error: Could not execute command. ({})", error); + } } } + None } diff --git a/src/main.rs b/src/main.rs index 9ec0bdf..6964d98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,6 +78,8 @@ fn main() { let mut buffer = String::new(); let mut buffer_updated: bool = false; let mut countdown = Countdown::new(); + // Child process of alarm_exec(). + let mut spawned: Option = None; // Initialise roster_width. layout.set_roster_width(alarm_roster.width()); @@ -254,7 +256,12 @@ fn main() { // Run command if configured. if config.alarm_exec.is_some() { - alarm_exec(&config, clock.elapsed); + if spawned.is_none() { + spawned = alarm_exec(&config, clock.elapsed); + } else { + // The last command is still running. + eprintln!("Not executing command, as its predecessor is still running"); + } } // Quit if configured. if config.auto_quit && !alarm_roster.active() { @@ -295,6 +302,26 @@ fn main() { countdown.draw(&mut stdout); } + // Check any spawned child process. + if let Some(ref mut child) = spawned { + match child.try_wait() { + // Process exited successfully. + Ok(Some(status)) if status.success() => spawned = None, + // Abnormal exit. + Ok(Some(status)) => { + eprintln!("Spawned process terminated with non-zero exit status. ({})", status); + spawned = None; + }, + // Process is still running. + Ok(None) => (), + // Other error. + Err(error) => { + eprintln!("Error executing command. ({})", error); + spawned = None; + }, + } + } + // Reset redraw_all and flush stdout. layout.force_redraw = false; stdout.flush().unwrap(); @@ -311,6 +338,21 @@ fn main() { cursor::Goto(1, 1), cursor::Show) .unwrap(); + + // Reset terminal. + drop(stdout); + drop(input_keys); + + // Wait for remaining spawned processes to exit. + if let Some(ref mut child) = spawned { + print!("Waiting for spawned processes (PID {}) to exit ...", child.id()); + std::io::stdout().flush().unwrap(); + + match child.wait() { + Ok(status) => println!(" ok ({})", status), + Err(error) => println!(" failed ({})", error), + } + } } fn usage() {