about summary refs log tree commit diff
path: root/library/std/src/sys/windows/fs.rs
diff options
context:
space:
mode:
authorChris Denton <christophersdenton@gmail.com>2022-04-26 01:08:46 +0100
committerChris Denton <christophersdenton@gmail.com>2022-04-26 01:08:46 +0100
commit8dc4696b3b8e048ddbc4a25953cccb567b27570c (patch)
tree7c27f1d9a2284f66d4a1eaded539f25e426541c2 /library/std/src/sys/windows/fs.rs
parent8b1f85caede44808e62542cfdff04787d70f8f7f (diff)
downloadrust-8dc4696b3b8e048ddbc4a25953cccb567b27570c.tar.gz
rust-8dc4696b3b8e048ddbc4a25953cccb567b27570c.zip
Retry deleting a directory
It's possible that a file in the directory is pending deletion. In that case we might succeed after a few attempts.
Diffstat (limited to 'library/std/src/sys/windows/fs.rs')
-rw-r--r--library/std/src/sys/windows/fs.rs17
1 files changed, 15 insertions, 2 deletions
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 618cbbb1817..e6f0f0f3023 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1018,6 +1018,10 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
 }
 
 fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> {
+    // When deleting files we may loop this many times when certain error conditions occur.
+    // This allows remove_dir_all to succeed when the error is temporary.
+    const MAX_RETRIES: u32 = 10;
+
     let mut buffer = DirBuff::new();
     let mut dirlist = vec![f.duplicate()?];
 
@@ -1040,7 +1044,6 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
                 )?;
                 dirlist.push(child_dir);
             } else {
-                const MAX_RETRIES: u32 = 10;
                 for i in 1..=MAX_RETRIES {
                     let result = open_link_no_reparse(&dir, name, c::SYNCHRONIZE | c::DELETE);
                     match result {
@@ -1062,7 +1065,17 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
         // If there were no more files then delete the directory.
         if !more_data {
             if let Some(dir) = dirlist.pop() {
-                delete(&dir)?;
+                // Retry deleting a few times in case we need to wait for a file to be deleted.
+                for i in 1..=MAX_RETRIES {
+                    let result = delete(&dir);
+                    if let Err(e) = result {
+                        if i == MAX_RETRIES || e.kind() != io::ErrorKind::DirectoryNotEmpty {
+                            return Err(e);
+                        }
+                    } else {
+                        break;
+                    }
+                }
             }
         }
     }