diff --git a/src/uu/sort/src/check.rs b/src/uu/sort/src/check.rs index a826bc75507..118d2d0fa6a 100644 --- a/src/uu/sort/src/check.rs +++ b/src/uu/sort/src/check.rs @@ -37,7 +37,7 @@ pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { let file = open(path)?; let (recycled_sender, recycled_receiver) = sync_channel(2); let (loaded_sender, loaded_receiver) = sync_channel(2); - thread::spawn({ + let reader_join_handle = thread::spawn({ let settings = settings.clone(); move || reader(file, &recycled_receiver, &loaded_sender, &settings) }); @@ -111,7 +111,10 @@ pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { drop(recycled_sender); while loaded_receiver.recv().is_ok() {} - result + // A read error ends the input early, so without this the part read so far + // would be checked and reported as sorted. + let reader_result = reader_join_handle.join().unwrap(); + result.and(reader_result) } /// The function running on the reader thread. diff --git a/src/uu/sort/src/chunks.rs b/src/uu/sort/src/chunks.rs index ee8261dd856..1a2d16da6f8 100644 --- a/src/uu/sort/src/chunks.rs +++ b/src/uu/sort/src/chunks.rs @@ -18,10 +18,11 @@ use std::{ use memchr::memchr_iter; use self_cell::self_cell; -use uucore::error::{UResult, USimpleError, strip_errno}; -use uucore::translate; +use uucore::error::UResult; -use crate::{GeneralBigDecimalParseResult, GlobalSettings, Line, numeric_str_cmp::NumInfo}; +use crate::{ + GeneralBigDecimalParseResult, GlobalSettings, Line, SortError, numeric_str_cmp::NumInfo, +}; const ALLOC_CHUNK_SIZE: usize = 64 * 1024; const MAX_TOKEN_BUFFER_BYTES: usize = 4 * 1024 * 1024; @@ -424,11 +425,8 @@ fn read_to_buffer( Err(e) if e.kind() == ErrorKind::Interrupted => { // retry } - Err(e) => { - return Err(USimpleError::new( - 2, - translate!("sort-read-failed", "error" => strip_errno(&e)), - )); + Err(error) => { + return Err(SortError::ChunkReadFailed { error }.into()); } } } diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 94edeaa8ca2..f035d79e685 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -161,6 +161,9 @@ pub enum SortError { error: std::io::Error, }, + #[error("{}", translate!("sort-read-failed", "error" => strip_errno(.error)))] + ChunkReadFailed { error: std::io::Error }, + #[error("{}", translate!("sort-open-tmp-file-failed", "error" => strip_errno(.error)))] OpenTmpFileFailed { error: std::io::Error }, diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 23dd109dd12..12fb8a84941 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -2335,6 +2335,22 @@ fn test_files0_from_non_utf8_filename() { .stderr_contains("sort: cannot read"); } +#[rstest::rstest] +#[case(&["-c", "dir"])] +#[case(&["-C", "dir"])] +#[case(&["-m", "input", "dir"])] +#[cfg(target_os = "linux")] +fn test_read_error_on_reader_thread(#[case] args: &[&str]) { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("dir"); + at.write("input", "a\nb\n"); + ucmd.args(args) + .fails_with_code(2) + .stderr_contains("sort: read failed: ") + .stderr_contains("Is a directory") + .stderr_does_not_contain("sort-read-failed"); +} + #[test] #[cfg(unix)] fn test_files0_from_unreadable_source() {