From e94d09da9449cabd7ece2acd98d52b1946a922a4 Mon Sep 17 00:00:00 2001 From: Rory Dudley Date: Tue, 27 Feb 2024 03:49:01 -0700 Subject: Remove custom errors and fix background forking Removes the custom errors in src/recite/erro.rs, and replaces them with std::io::Errors throughout (recite(), incant_, macros). Fixed a bug with the way forking to the background is handled, where registering the signal handler in main for all processes would break couplets (i.e. pipes). Instead, this sets up a new signal handler each time a process is forked into the background. It uses a Vec to keep track of all the background processes. --- src/recite.rs | 60 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 20 deletions(-) (limited to 'src/recite.rs') diff --git a/src/recite.rs b/src/recite.rs index bfcd6b1..f21a905 100644 --- a/src/recite.rs +++ b/src/recite.rs @@ -1,14 +1,13 @@ -pub mod erro; pub mod path; mod ps; -use crate::ctask; -use crate::task; +use crate::{ctask, task}; use core::fmt; -use erro::Mishap; +use libc::{waitpid, WNOHANG}; use path::prefresh; use std::io::{self, Write}; use std::path::Path; use std::process::{exit, Command, Stdio}; +use std::sync::{Arc, Mutex}; /// Describes the ending of a [Verse] /// @@ -50,29 +49,25 @@ impl fmt::Display for Meter { } impl Meter { - fn incant_none(verse: &Verse, out: &mut String) -> Result { + fn incant_none(verse: &Verse, out: &mut String) -> Result { let child = task!(verse, out); - let output = child - .wait_with_output() - .map_err(|_| Mishap::Terminated(verse.stanza.to_string()))?; + let output = child.wait_with_output()?; if !output.status.success() { - return Err(Mishap::Else(verse.stanza.to_string())); + return Ok(output.status.code().unwrap_or(-1)); } Ok(output.status.code().unwrap_or(0)) } - fn incant_couplet(verse: &Verse, out: &mut String) -> Result { + fn incant_couplet(verse: &Verse, out: &mut String) -> Result { let child = ctask!(verse, out); - let output = child - .wait_with_output() - .map_err(|_| Mishap::Terminated(verse.stanza.to_string()))?; + let output = child.wait_with_output()?; if !output.status.success() { - return Err(Mishap::Else(verse.stanza.to_string())); + return Ok(output.status.code().unwrap_or(-1)); } out.push_str( @@ -84,17 +79,41 @@ impl Meter { Ok(output.status.code().unwrap_or(0)) } - fn incant_quiet(verse: &Verse, out: &mut String) -> Result { + fn incant_quiet( + verse: &Verse, + out: &mut String, + pids: &mut Arc>>, + ) -> Result { let child = task!(verse, out); println!("[&] {}", child.id()); + + pids.lock().unwrap().push(child.id() as i32); + let stanza = verse.stanza.to_string(); + let pids = Arc::clone(pids); + + unsafe { + signal_hook::low_level::register(signal_hook::consts::SIGCHLD, move || { + for pid in pids.lock().unwrap().iter() { + let mut pid = *pid; + let mut status: i32 = 0; + pid = waitpid(pid, &mut status, WNOHANG); + if pid > 0 { + print!("\n[&] + done {}", stanza); + io::stdout().flush().unwrap(); + } + } + }) + .unwrap(); + } + Ok(0) } - fn incant_and(verse: &Verse, out: &mut String) -> Result { + fn incant_and(verse: &Verse, out: &mut String) -> Result { Meter::incant_none(verse, out) } - fn incant_string(verse: &Verse, out: &mut String) -> Result { + fn incant_string(verse: &Verse, out: &mut String) -> Result { Meter::incant_none(verse, out) } } @@ -314,9 +333,10 @@ impl Poem { /// None => {} /// } /// ``` - pub fn recite(&self, path: &Vec<&Path>, bins: &mut Vec) -> Result<(), Mishap> { + pub fn recite(&self, path: &Vec<&Path>, bins: &mut Vec) -> Result<(), io::Error> { // Variable for storing the output of a piped verse let mut out: String = String::new(); + let mut pids: Arc>> = Arc::new(Mutex::new(Vec::new())); // Loop through each verse in the poem for verse in self.verses.iter() { @@ -359,12 +379,12 @@ impl Poem { match verse.meter { Meter::None => Meter::incant_none(verse, &mut out)?, Meter::Couplet => Meter::incant_couplet(verse, &mut out)?, - Meter::Quiet => Meter::incant_quiet(verse, &mut out)?, + Meter::Quiet => Meter::incant_quiet(verse, &mut out, &mut pids)?, Meter::And => Meter::incant_and(verse, &mut out)?, Meter::String => match Meter::incant_string(verse, &mut out) { Ok(_) => 0, Err(e) => { - eprintln!("dwvsh: {}", e); + eprintln!("dwvsh: {}", e.to_string().to_lowercase()); 1 } }, -- cgit v1.2.3