Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/uu/sort/src/ext_sort/threaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub fn ext_sort(

// Test if compression program exists and works, disable if not
let mut effective_settings = settings.clone();
// Keep the error until we know compression is actually needed.
let mut compress_prog_error = None;
if let Some(ref prog) = settings.compress_prog {
// Test the compression program by trying to spawn it
match std::process::Command::new(prog)
Expand All @@ -65,12 +67,7 @@ pub fn ext_sort(
let _ = child.kill();
}
Err(err) => {
// Print the error and disable compression
let _ = writeln!(
stderr(),
"sort: could not run compress program '{prog}': {}",
strip_errno(&err)
);
compress_prog_error = Some((prog.clone(), err));
effective_settings.compress_prog = None;
}
}
Expand All @@ -80,6 +77,7 @@ pub fn ext_sort(
reader_writer::<_, WriteableCompressedTmpFile>(
files,
&effective_settings,
None,
&sorted_receiver,
recycled_sender,
output,
Expand All @@ -89,6 +87,7 @@ pub fn ext_sort(
reader_writer::<_, WriteablePlainTmpFile>(
files,
&effective_settings,
compress_prog_error,
&sorted_receiver,
recycled_sender,
output,
Expand All @@ -103,6 +102,7 @@ fn reader_writer<
>(
files: F,
settings: &GlobalSettings,
compress_prog_error: Option<(String, std::io::Error)>,
receiver: &Receiver<Chunk>,
sender: SyncSender<Chunk>,
output: Output,
Expand All @@ -125,6 +125,7 @@ fn reader_writer<
separator,
buffer_size,
settings,
compress_prog_error,
receiver,
sender,
)?;
Expand Down Expand Up @@ -207,12 +208,14 @@ enum ReadResult<I: WriteableTmpFile> {
WroteChunksToFile { tmp_files: Vec<I::Closed> },
}
/// The function that is executed on the reader/writer thread.
#[allow(clippy::too_many_arguments)]
fn read_write_loop<I: WriteableTmpFile>(
mut files: impl Iterator<Item = UResult<Box<dyn Read + Send>>>,
tmp_dir: &mut TmpDirWrapper,
separator: u8,
buffer_size: usize,
settings: &GlobalSettings,
compress_prog_error: Option<(String, std::io::Error)>,
receiver: &Receiver<Chunk>,
sender: SyncSender<Chunk>,
) -> UResult<ReadResult<I>> {
Expand Down Expand Up @@ -249,6 +252,15 @@ fn read_write_loop<I: WriteableTmpFile>(
}
}

// The input did not fit into the first two in-memory chunks.
if let Some((prog, err)) = compress_prog_error {
let _ = writeln!(
stderr(),
"sort: could not run compress program '{prog}': {}",
strip_errno(&err)
);
}

let mut sender_option = Some(sender);
let mut tmp_files = vec![];
loop {
Expand Down
16 changes: 15 additions & 1 deletion tests/by-util/test_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ fn test_compress_fail() {
"--compress-program",
"nonexistent-program",
"-S",
"10",
"1K",
])
.succeeds();

Expand All @@ -1394,6 +1394,20 @@ fn test_compress_fail() {
assert_eq!(result.stdout_str(), expected);
}

#[test]
#[cfg(unix)]
fn test_input_error_before_compression_is_needed() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("input", "b\na\n");
at.mkdir("directory");

ucmd.args(&["--compress-program=nonexistent", "input", "directory"])
.fails_with_code(2)
.no_stdout()
.stderr_contains("Is a directory")
.stderr_does_not_contain("compress program");
}

#[test]
fn test_merge_batches() {
new_ucmd!()
Expand Down
Loading