Tend to spawned processes.

This commit is contained in:
shy 2021-04-08 11:17:06 +02:00
parent 91d3e81eca
commit 5e01fbe066
2 changed files with 52 additions and 10 deletions

View file

@ -1,5 +1,5 @@
use std::io::Write; use std::io::Write;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio, Child};
use termion::{color, cursor, style}; use termion::{color, cursor, style};
use termion::raw::RawTerminal; use termion::raw::RawTerminal;
use crate::{Clock, Config, Layout, Position}; use crate::{Clock, Config, Layout, Position};
@ -267,7 +267,7 @@ impl AlarmRoster {
} }
// Execute the command given on the command line. // 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<Child> {
let mut args: Vec<String> = Vec::new(); let mut args: Vec<String> = Vec::new();
let time: String; let time: String;
@ -283,14 +283,14 @@ pub fn alarm_exec(config: &Config, elapsed: u32) {
args.push(s.replace("{}", &time)); args.push(s.replace("{}", &time));
} }
if Command::new(&exec[0]) match Command::new(&exec[0]).args(&args[1..])
.args(&args[1..]) .stdout(Stdio::null()).stdin(Stdio::null()).spawn() {
.stdout(Stdio::null()) Ok(child) => return Some(child),
.stdin(Stdio::null()) Err(error) => {
.spawn().is_err() { eprintln!("Error: Could not execute command. ({})", error);
eprintln!("Error: Could not execute command");
} }
} }
}
None
} }

View file

@ -78,6 +78,8 @@ fn main() {
let mut buffer = String::new(); let mut buffer = String::new();
let mut buffer_updated: bool = false; let mut buffer_updated: bool = false;
let mut countdown = Countdown::new(); let mut countdown = Countdown::new();
// Child process of alarm_exec().
let mut spawned: Option<std::process::Child> = None;
// Initialise roster_width. // Initialise roster_width.
layout.set_roster_width(alarm_roster.width()); layout.set_roster_width(alarm_roster.width());
@ -254,7 +256,12 @@ fn main() {
// Run command if configured. // Run command if configured.
if config.alarm_exec.is_some() { 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. // Quit if configured.
if config.auto_quit && !alarm_roster.active() { if config.auto_quit && !alarm_roster.active() {
@ -295,6 +302,26 @@ fn main() {
countdown.draw(&mut stdout); 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. // Reset redraw_all and flush stdout.
layout.force_redraw = false; layout.force_redraw = false;
stdout.flush().unwrap(); stdout.flush().unwrap();
@ -311,6 +338,21 @@ fn main() {
cursor::Goto(1, 1), cursor::Goto(1, 1),
cursor::Show) cursor::Show)
.unwrap(); .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() { fn usage() {