From 2b24b1a753f1b40518206b63f4253048bfe13669 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Aug 2025 17:08:54 +0200 Subject: [PATCH] Ensure error reporting when using buffered file writes Quoting from the BufWriter docs: >It is critical to call flush before BufWriter is dropped. Though >dropping will attempt to flush the contents of the buffer, any errors >that happen in the process of dropping will be ignored. Calling flush >ensures that the buffer is empty and thus dropping will not even >attempt file operations. --- api/cpp/cbindgen.rs | 4 ++++ api/rs/build/lib.rs | 2 ++ internal/compiler/build.rs | 1 + internal/compiler/generator/cpp.rs | 4 +++- internal/compiler/generator/cpp_live_reload.rs | 4 +++- tests/doctests/build.rs | 2 ++ tests/driver/cpp/build.rs | 2 ++ tests/driver/rust/build.rs | 4 ++++ tests/screenshots/build.rs | 4 ++++ tools/compiler/main.rs | 10 ++++------ tools/lsp/fmt/tool.rs | 5 +++-- tools/updater/main.rs | 1 + xtask/src/slintdocs.rs | 4 ++++ 13 files changed, 37 insertions(+), 10 deletions(-) diff --git a/api/cpp/cbindgen.rs b/api/cpp/cbindgen.rs index c03cfe1752b..44c627eaf93 100644 --- a/api/cpp/cbindgen.rs +++ b/api/cpp/cbindgen.rs @@ -99,6 +99,8 @@ namespace slint::platform::key_codes {{ i_slint_common::for_each_special_keys!(print_key_codes); writeln!(enums_pub, "}}")?; + enums_priv.flush()?; + enums_pub.flush()?; Ok(()) } @@ -184,6 +186,8 @@ fn builtin_structs(path: &Path) -> anyhow::Result<()> { i_slint_common::for_each_builtin_structs!(print_structs); writeln!(structs_priv, "}}")?; writeln!(structs_pub, "}}")?; + structs_priv.flush()?; + structs_pub.flush()?; Ok(()) } diff --git a/api/rs/build/lib.rs b/api/rs/build/lib.rs index bba7c0af9cf..228283f0901 100644 --- a/api/rs/build/lib.rs +++ b/api/rs/build/lib.rs @@ -522,6 +522,8 @@ pub fn compile_with_output_path( } } + code_formatter.sink.flush().map_err(CompileError::SaveError)?; + Ok(dependencies) } diff --git a/internal/compiler/build.rs b/internal/compiler/build.rs index 09aab16ec80..a8cbb96b2e5 100644 --- a/internal/compiler/build.rs +++ b/internal/compiler/build.rs @@ -38,6 +38,7 @@ fn widget_library() -> &'static [(&'static str, &'static BuiltinDirectory<'stati } writeln!(file, "]\n}}")?; + file.flush()?; println!("cargo:rustc-env=SLINT_WIDGETS_LIBRARY={}", output_file_path.display()); diff --git a/internal/compiler/generator/cpp.rs b/internal/compiler/generator/cpp.rs index 197fbb2fe6d..03e03531bb2 100644 --- a/internal/compiler/generator/cpp.rs +++ b/internal/compiler/generator/cpp.rs @@ -873,7 +873,9 @@ pub fn generate( for (cpp_file_name, cpp_file) in config.cpp_files.iter().zip(cpp_files) { use std::io::Write; - write!(&mut BufWriter::new(std::fs::File::create(&cpp_file_name)?), "{cpp_file}")?; + let mut cpp_writer = BufWriter::new(std::fs::File::create(&cpp_file_name)?); + write!(&mut cpp_writer, "{cpp_file}")?; + cpp_writer.flush()?; } Ok(file) diff --git a/internal/compiler/generator/cpp_live_reload.rs b/internal/compiler/generator/cpp_live_reload.rs index a93bfb2981f..32ee6d3c74d 100644 --- a/internal/compiler/generator/cpp_live_reload.rs +++ b/internal/compiler/generator/cpp_live_reload.rs @@ -52,7 +52,9 @@ pub fn generate( let cpp_files = file.split_off_cpp_files(config.header_include, config.cpp_files.len()); for (cpp_file_name, cpp_file) in config.cpp_files.iter().zip(cpp_files) { use std::io::Write; - write!(&mut BufWriter::new(std::fs::File::create(&cpp_file_name)?), "{cpp_file}")?; + let mut cpp_writer = BufWriter::new(std::fs::File::create(&cpp_file_name)?); + write!(&mut cpp_writer, "{cpp_file}")?; + cpp_writer.flush()?; } Ok(file) diff --git a/tests/doctests/build.rs b/tests/doctests/build.rs index 1774c8fd904..efe3047e522 100644 --- a/tests/doctests/build.rs +++ b/tests/doctests/build.rs @@ -86,6 +86,8 @@ fn main() -> Result<(), Box> { println!("cargo:rerun-if-changed={}", path.display()); } + tests_file.flush()?; + println!("cargo:rustc-env=TEST_FUNCTIONS={}", tests_file_path.to_string_lossy()); println!("cargo:rustc-env=SLINT_ENABLE_EXPERIMENTAL_FEATURES=1"); diff --git a/tests/driver/cpp/build.rs b/tests/driver/cpp/build.rs index 9b4e1fd5306..bf71f34d251 100644 --- a/tests/driver/cpp/build.rs +++ b/tests/driver/cpp/build.rs @@ -69,6 +69,8 @@ fn main() -> Result<(), Box> { )?; } + tests_file.flush()?; + println!("cargo:rustc-env=TEST_FUNCTIONS={}", tests_file_path.to_string_lossy()); println!("cargo:rustc-env=SLINT_ENABLE_EXPERIMENTAL_FEATURES=1"); Ok(()) diff --git a/tests/driver/rust/build.rs b/tests/driver/rust/build.rs index 98485daf9af..2b7f3e10a5a 100644 --- a/tests/driver/rust/build.rs +++ b/tests/driver/rust/build.rs @@ -66,8 +66,12 @@ fn main() -> std::io::Result<()> { x.source.replace('\n', "\n ") )?; } + + output.flush()?; } + generated_file.flush()?; + // By default resources are embedded. The WASM example builds provide test coverage for that. This switch // provides test coverage for the non-embedding case, compiling tests without embedding the images. if !live_reload { diff --git a/tests/screenshots/build.rs b/tests/screenshots/build.rs index 381186b38d8..afd16fdaa82 100644 --- a/tests/screenshots/build.rs +++ b/tests/screenshots/build.rs @@ -156,8 +156,12 @@ fn main() -> std::io::Result<()> { Ok(()) }}", )?; + + output.flush()?; } + generated_file.flush()?; + //Make sure to use a consistent style println!("cargo:rustc-env=SLINT_STYLE=fluent"); println!("cargo:rustc-env=SLINT_ENABLE_EXPERIMENTAL_FEATURES=1"); diff --git a/tools/compiler/main.rs b/tools/compiler/main.rs index 1594c7aa291..7c3648853d8 100644 --- a/tools/compiler/main.rs +++ b/tools/compiler/main.rs @@ -198,12 +198,9 @@ fn main() -> std::io::Result<()> { if args.output == std::path::Path::new("-") { generator::generate(format, &mut std::io::stdout(), &doc, &loader.compiler_config)?; } else { - generator::generate( - format, - &mut BufWriter::new(std::fs::File::create(&args.output)?), - &doc, - &loader.compiler_config, - )?; + let mut file_writer = BufWriter::new(std::fs::File::create(&args.output)?); + generator::generate(format, &mut file_writer, &doc, &loader.compiler_config)?; + file_writer.flush()?; } if let Some(depfile) = args.depfile { @@ -223,6 +220,7 @@ fn main() -> std::io::Result<()> { } writeln!(f)?; + f.flush()?; } diag.print_warnings_and_exit_on_error(); Ok(()) diff --git a/tools/lsp/fmt/tool.rs b/tools/lsp/fmt/tool.rs index 684394aefbf..adbaae54d6f 100644 --- a/tools/lsp/fmt/tool.rs +++ b/tools/lsp/fmt/tool.rs @@ -28,7 +28,7 @@ pub fn run(files: &[std::path::PathBuf], inplace: bool) -> std::io::Result<()> { if inplace { let file = BufWriter::new(std::fs::File::create(&path)?); - process_file(source, path, file)? + process_file(source, path, file)?; } else { process_file(source, path, std::io::stdout())? } @@ -53,7 +53,8 @@ fn process_rust_file(source: String, mut file: impl Write) -> std::io::Result<() diag.print(); } } - file.write_all(&source.as_bytes()[last..]) + file.write_all(&source.as_bytes()[last..])?; + file.flush() } /// FIXME! this is duplicated with the updater diff --git a/tools/updater/main.rs b/tools/updater/main.rs index bf7aacad3bf..16aec29f2d7 100644 --- a/tools/updater/main.rs +++ b/tools/updater/main.rs @@ -133,6 +133,7 @@ fn process_file( file.write_all(&source.as_bytes()[len..])?; diag.print(); } + file.flush()?; Ok(()) } diff --git a/xtask/src/slintdocs.rs b/xtask/src/slintdocs.rs index cf4932d5d04..ef83076844e 100644 --- a/xtask/src/slintdocs.rs +++ b/xtask/src/slintdocs.rs @@ -65,6 +65,8 @@ description: {0} content v.key, v.description )?; } + + file.flush()?; } Ok(()) } @@ -260,6 +262,8 @@ description: {0} content f.key, f.type_name, f.description )?; } + + file.flush()?; } Ok(())