From 2ee998c462f5c104937474196bb3cef31f1fc399 Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Sat, 25 Jan 2025 22:04:15 +0000 Subject: [PATCH] fix: Handle Interrupted Error Rust may throw Interrupted errors while scanning filesystem. These may be retried: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.Interrupted --- src/dir_walker.rs | 60 +++++++++++++++++++++++++++++++++-------------- src/progress.rs | 1 + 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/dir_walker.rs b/src/dir_walker.rs index 8f87de0c..f8566c80 100644 --- a/src/dir_walker.rs +++ b/src/dir_walker.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; use std::fs; +use std::io::Error; use std::sync::Arc; use std::sync::Mutex; @@ -178,8 +179,8 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool { fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option { let prog_data = &walk_data.progress_data; - let errors = &walk_data.errors; + let errors = &walk_data.errors; if errors.lock().unwrap().abort { return None; } @@ -229,8 +230,9 @@ fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option { } } Err(ref failed) => { - let mut editable_error = errors.lock().unwrap(); - editable_error.no_permissions.insert(failed.to_string()); + if handle_error_and_retry(failed, &dir, walk_data) { + return walk(dir.clone(), walk_data, depth); + } } } None @@ -238,21 +240,11 @@ fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option { .collect() } Err(failed) => { - let mut editable_error = errors.lock().unwrap(); - match failed.kind() { - std::io::ErrorKind::PermissionDenied => { - editable_error - .no_permissions - .insert(dir.to_string_lossy().into()); - } - std::io::ErrorKind::NotFound => { - editable_error.file_not_found.insert(failed.to_string()); - } - _ => { - editable_error.unknown_error.insert(failed.to_string()); - } + if handle_error_and_retry(&failed, &dir, walk_data) { + return walk(dir, walk_data, depth); + } else { + vec![] } - vec![] } } } else { @@ -274,6 +266,40 @@ fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option { build_node(dir, children, is_symlink, false, depth, walk_data) } +fn handle_error_and_retry(failed: &Error, dir: &PathBuf, walk_data: &WalkData) -> bool { + let mut editable_error = walk_data.errors.lock().unwrap(); + match failed.kind() { + std::io::ErrorKind::PermissionDenied => { + editable_error + .no_permissions + .insert(dir.to_string_lossy().into()); + } + std::io::ErrorKind::InvalidInput => { + editable_error + .no_permissions + .insert(dir.to_string_lossy().into()); + } + std::io::ErrorKind::NotFound => { + editable_error.file_not_found.insert(failed.to_string()); + } + std::io::ErrorKind::Interrupted => { + let mut editable_error = walk_data.errors.lock().unwrap(); + editable_error.interruped_error += 1; + if editable_error.interruped_error > 3 { + panic!("Multiple Interrupted Errors occured while scanning filesystem. Aborting"); + } else { + return true; + } + } + _ => { + println!("{:?} {:?}", failed, dir); + println!("FISH"); + editable_error.unknown_error.insert(failed.to_string()); + } + } + false +} + mod tests { #[allow(unused_imports)] diff --git a/src/progress.rs b/src/progress.rs index 45def8fd..1cabf7e4 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -78,6 +78,7 @@ pub struct RuntimeErrors { pub no_permissions: HashSet, pub file_not_found: HashSet, pub unknown_error: HashSet, + pub interruped_error: i32, pub abort: bool, }