summaryrefslogtreecommitdiff
path: root/cli/util
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-05-31 23:25:08 -0400
committerGitHub <noreply@github.com>2024-05-31 23:25:08 -0400
commit38ff9faff639385c10ccb6412470e1355c73327c (patch)
tree7bd288fc54cb31eb15fa9a1fbd68528c282f3579 /cli/util
parentf5c239f3772e7e87006dbc1ed763951960e4b178 (diff)
fix: retry writing lockfile on failure (#24052)
Ran into this running the deno_graph ecosystem tests where many processes writing to the same path at the same time would cause an error.
Diffstat (limited to 'cli/util')
-rw-r--r--cli/util/fs.rs29
1 files changed, 27 insertions, 2 deletions
diff --git a/cli/util/fs.rs b/cli/util/fs.rs
index 9bdb1d014..5adb777b0 100644
--- a/cli/util/fs.rs
+++ b/cli/util/fs.rs
@@ -32,6 +32,28 @@ use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::progress_bar::ProgressMessagePrompt;
+pub fn atomic_write_file_with_retries<T: AsRef<[u8]>>(
+ file_path: &Path,
+ data: T,
+ mode: u32,
+) -> std::io::Result<()> {
+ let mut count = 0;
+ loop {
+ match atomic_write_file(file_path, data.as_ref(), mode) {
+ Ok(()) => return Ok(()),
+ Err(err) => {
+ if count >= 5 {
+ // too many retries, return the error
+ return Err(err);
+ }
+ count += 1;
+ let sleep_ms = std::cmp::min(50, 10 * count);
+ std::thread::sleep(std::time::Duration::from_millis(sleep_ms));
+ }
+ }
+ }
+}
+
/// Writes the file to the file system at a temporary path, then
/// renames it to the destination in a single sys call in order
/// to never leave the file system in a corrupted state.
@@ -50,8 +72,11 @@ pub fn atomic_write_file<T: AsRef<[u8]>>(
mode: u32,
) -> std::io::Result<()> {
write_file(temp_file_path, data, mode)?;
- std::fs::rename(temp_file_path, file_path)?;
- Ok(())
+ std::fs::rename(temp_file_path, file_path).map_err(|err| {
+ // clean up the created temp file on error
+ let _ = std::fs::remove_file(temp_file_path);
+ err
+ })
}
fn inner(file_path: &Path, data: &[u8], mode: u32) -> std::io::Result<()> {