diff --git a/src/coverage_printer.rs b/src/coverage_printer.rs index 042f88b..0ed4b8a 100644 --- a/src/coverage_printer.rs +++ b/src/coverage_printer.rs @@ -118,6 +118,13 @@ impl CoveragePrinter { } } } + // Output to a file is buffered, so the last writes only reach the disk + // here; a failure (e.g. a full disk) must not leave a truncated file + // behind a successful exit. + if let Err(e) = print_stream.flush() { + error!("Failed to write output: {e}"); + process::exit(1); + } } pub fn print_headers( diff --git a/src/lib.rs b/src/lib.rs index b50cc0e..ab83500 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,7 +79,10 @@ impl FlagFilter { } pub struct OutputWriter { - pub output_file: Option>>, + // Buffered: output is written in many small pieces (one per field), and an + // unbuffered File turns each into a write syscall. Flushed, with errors + // checked, by CoveragePrinter::finalise_printing. + pub output_file: Option>>>, } impl OutputWriter { @@ -95,9 +98,9 @@ impl OutputWriter { info!("Writing output to file: {file_path}"); OutputWriter { output_file: Some(Arc::new(std::sync::Mutex::new( - std::fs::File::create(path).unwrap_or_else(|_| { - panic!("Failed to create output file: {}", file_path) - }), + std::io::BufWriter::new(std::fs::File::create(path).unwrap_or_else( + |_| panic!("Failed to create output file: {}", file_path), + )), ))), } }