From 9e31af3ff2ae70a96f655ba29165cb8ad7f1af56 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 13 Oct 2026 08:04:13 +0300 Subject: [PATCH] fix(save): retry the atomic replace while the drawing is briefly in use Sync clients, indexers and virus scanners open a freshly written file for a moment without delete sharing, which refuses ReplaceFileW with a sharing violation. Saving straight after Save As into a Dropbox folder hit this every time. The replace now retries for about two seconds before reporting the file in use. Fixes #1712 Co-Authored-By: Claude Opus 5.5 --- src/io/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/io/mod.rs b/src/io/mod.rs index 2cbd5a5ed..99e1611ce 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -2254,7 +2254,17 @@ fn replace_save_file(temp_path: &Path, path: &Path) -> std::io::Result<()> { // drawing that was hidden before the save stays hidden. (#1414) let was_hidden = std::fs::metadata(path) .is_ok_and(|meta| meta.file_attributes() & FILE_ATTRIBUTE_HIDDEN != 0); - replace_save_file_inner(temp_path, path)?; + // Sync clients (Dropbox, OneDrive), indexers and virus scanners open a + // freshly written drawing for a moment without delete sharing, which + // refuses the replace. Retry briefly before reporting the file in use. + let mut attempt = 0; + while let Err(error) = replace_save_file_inner(temp_path, path) { + attempt += 1; + if attempt >= 10 || !replace_error_is_file_in_use(&error) { + return Err(error); + } + std::thread::sleep(std::time::Duration::from_millis(200)); + } if !was_hidden { if let Ok(meta) = std::fs::metadata(path) { let attributes = meta.file_attributes();