From fcf066aff5eb44802865b532a1163b495916304a Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Thu, 8 May 2025 03:12:32 -0700 Subject: [PATCH] fs: Fall back from atomic write to regular fs write when file handle is in use on Windows (#30222) Closes #30054 For reference, another way to work around this is to drop the file handle which we can't do in this case, as it would require reopening the settings.json worktree, which is a rather unpleasant fix. Another approach might be to open the file handle with some special flags, but I couldn't get that to work at the time of writing. Release Notes: - Fixed "Backup and Update" in settings migration not working on Windows. --- crates/fs/src/fs.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 93cd1eb593977d73060e26655ac69f1ac2b5115e..d1c59a2b58c9026fd5722ea41035daeab565820b 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -546,7 +546,24 @@ impl Fs for RealFs { NamedTempFile::new() }?; tmp_file.write_all(data.as_bytes())?; - tmp_file.persist(path)?; + + let result = tmp_file.persist(&path); + if cfg!(target_os = "windows") { + // If file handle is already in used we receive error: + // + // failed to persist temporary file: + // Access is denied. (os error 5) + // + // So we use direct fs write instead to avoid it. + // https://github.com/zed-industries/zed/issues/30054 + if let Err(persist_err) = &result { + if persist_err.error.raw_os_error() == Some(5) { + return std::fs::write(&path, data.as_bytes()).map_err(Into::into); + } + } + } + result?; + Ok::<(), anyhow::Error>(()) }) .await?;