summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Nguyen <benjamin.van.nguyen@gmail.com>2023-07-02 11:48:27 +0700
committerBenjamin Nguyen <benjamin.van.nguyen@gmail.com>2023-07-02 11:48:27 +0700
commit9fd3eff045b9e6bc054a494ef9e2d455baf0f73b (patch)
tree5b6ee694b35f8c811abd2a14135250155f222f13
parent43052c5b06cd26efe43cddb7d5923cb6600a6044 (diff)
resolve print race which prevents proper error message from being displayed sometimesexit-race
-rw-r--r--src/main.rs20
-rw-r--r--src/progress.rs37
-rw-r--r--src/tree/mod.rs11
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 || {