diff options
author | Benjamin Nguyen <benjamin.van.nguyen@gmail.com> | 2023-07-02 11:48:27 +0700 |
---|---|---|
committer | Benjamin Nguyen <benjamin.van.nguyen@gmail.com> | 2023-07-02 11:48:27 +0700 |
commit | 9fd3eff045b9e6bc054a494ef9e2d455baf0f73b (patch) | |
tree | 5b6ee694b35f8c811abd2a14135250155f222f13 | |
parent | 43052c5b06cd26efe43cddb7d5923cb6600a6044 (diff) |
resolve print race which prevents proper error message from being displayed sometimesexit-race
-rw-r--r-- | src/main.rs | 20 | ||||
-rw-r--r-- | src/progress.rs | 37 | ||||
-rw-r--r-- | src/tree/mod.rs | 11 |
3 files changed, 30 insertions, 38 deletions
diff --git a/src/main.rs b/src/main.rs index 11481fb..c9d4713 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,16 +10,13 @@ clippy::style, clippy::suspicious )] -#![allow( - clippy::cast_precision_loss, - clippy::struct_excessive_bools, -)] +#![allow(clippy::cast_precision_loss, clippy::struct_excessive_bools)] use clap::CommandFactory; use context::{layout, Context}; use progress::{Indicator, IndicatorHandle, Message}; use render::{Engine, Flat, FlatInverted, Inverted, Regular}; -use std::{error::Error, io::stdout, process::ExitCode, sync::Arc}; +use std::{error::Error, io::stdout, process::ExitCode}; use tree::Tree; /// Operations to wrangle ANSI escaped strings. @@ -78,7 +75,7 @@ fn run() -> Result<(), Box<dyn Error>> { let indicator = Indicator::maybe_init(&ctx); let (tree, ctx) = { - match Tree::try_init(ctx, indicator.clone()) { + match Tree::try_init(ctx, indicator.as_ref()) { Ok(res) => res, Err(err) => { IndicatorHandle::terminate(indicator); @@ -104,12 +101,11 @@ fn run() -> Result<(), Box<dyn Error>> { if let Some(mut progress) = indicator { progress.mailbox().send(Message::RenderReady)?; - if let Some(hand) = Arc::get_mut(&mut progress) { - hand.join_handle - .take() - .map(|h| h.join().unwrap()) - .transpose()?; - } + progress + .join_handle + .take() + .map(|h| h.join().unwrap()) + .transpose()?; } #[cfg(debug_assertions)] diff --git a/src/progress.rs b/src/progress.rs index 0f81a2b..73ca59a 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -6,10 +6,7 @@ use crossterm::{ }; use std::{ io::{self, Write}, - sync::{ - mpsc::{self, SendError, SyncSender}, - Arc, - }, + sync::mpsc::{self, SendError, SyncSender}, thread::{self, JoinHandle}, }; @@ -101,22 +98,25 @@ impl IndicatorHandle { } /// Analogous to [`Self::try_terminate`] but panics if failure. - pub fn terminate(this: Option<Arc<Self>>) { + pub fn terminate(this: Option<Self>) { Self::try_terminate(this).expect("Failed to properly terminate the progress indicator"); } /// Attempts to terminate the [`Indicator`] with cleanup. - pub fn try_terminate(this: Option<Arc<Self>>) -> Result<(), Error> { + pub fn try_terminate(this: Option<Self>) -> Result<(), Error> { if let Some(mut handle) = this { - eprintln!("{}", Arc::strong_count(&handle)); - handle.mailbox().send(Message::Finish)?; - - if let Some(hand) = Arc::get_mut(&mut handle) { - hand.join_handle - .take() - .map(|h| h.join().unwrap()) - .transpose()?; - } + // This is allowed to fail silently. If user administers interrupt then the `Indicator` + // will be dropped along with the receiving end of the `mailbox`. + // + // If user does not administer interrupt but file-system traversal fails for whatever + // reason then this will proceed as normal. + let _ = handle.mailbox().send(Message::Finish); + + handle + .join_handle + .take() + .map(|h| h.join().unwrap()) + .transpose()?; } Ok(()) @@ -128,15 +128,14 @@ impl<'a> Indicator<'a> { /// a progress indicator is enabled via [`Context`]. Upon initialization an interrupt handler is /// also registered. Sources of panic can come from [`IndicatorHandle::terminate`] or /// [`ctrlc::set_handler`]. - pub fn maybe_init(ctx: &Context) -> Option<Arc<IndicatorHandle>> { + pub fn maybe_init(ctx: &Context) -> Option<IndicatorHandle> { (ctx.stdout_is_tty && !ctx.no_progress) .then(Indicator::measure) .map(|indicator| { - let indicator = Arc::new(indicator); - let arc = indicator.clone(); + let mailbox = indicator.mailbox(); let int_handler = move || { - IndicatorHandle::terminate(Some(arc.clone())); + let _ = mailbox.try_send(Message::Finish); tty::restore_tty(); }; diff --git a/src/tree/mod.rs b/src/tree/mod.rs index dc6658b..be2b7ee 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -16,10 +16,7 @@ use std::{ fs, path::PathBuf, result::Result as StdResult, - sync::{ - mpsc::{self, Sender}, - Arc, - }, + sync::mpsc::{self, Sender}, thread, }; use visitor::{BranchVisitorBuilder, TraversalState}; @@ -54,7 +51,7 @@ impl Tree { /// various properties necessary to render output. pub fn try_init( mut ctx: Context, - indicator: Option<Arc<IndicatorHandle>>, + indicator: Option<&IndicatorHandle>, ) -> Result<(Self, Context)> { let mut column_properties = column::Properties::from(&ctx); @@ -102,12 +99,12 @@ impl Tree { fn traverse( ctx: &Context, column_properties: &mut column::Properties, - indicator: Option<Arc<IndicatorHandle>>, + indicator: Option<&IndicatorHandle>, ) -> Result<(Arena<Node>, NodeId)> { let walker = WalkParallel::try_from(ctx)?; let (tx, rx) = mpsc::channel(); - let progress_indicator_mailbox = indicator.map(|arc| arc.mailbox()); + let progress_indicator_mailbox = indicator.map(IndicatorHandle::mailbox); thread::scope(|s| { let res = s.spawn(move || { |