diff options
| author | Chris Denton <chris@chrisdenton.dev> | 2025-04-20 15:29:17 +0000 |
|---|---|---|
| committer | Chris Denton <chris@chrisdenton.dev> | 2025-04-25 11:28:36 +0000 |
| commit | c07054bdd1f8927fef5b1665debff9cb27452cc0 (patch) | |
| tree | 53af58861dbbb9d45db31c52ab8898e12b2bd35c /compiler/rustc_fs_util/src | |
| parent | 077cedc2afa8ac0b727b7a6cbe012940ba228deb (diff) | |
| download | rust-c07054bdd1f8927fef5b1665debff9cb27452cc0.tar.gz rust-c07054bdd1f8927fef5b1665debff9cb27452cc0.zip | |
Retry if creating temp fails with access denied
On Windows, if creating a temporary directory fails with permission denied then use a retry/backoff loop. This hopefully fixes a recuring error in our CI.
Diffstat (limited to 'compiler/rustc_fs_util/src')
| -rw-r--r-- | compiler/rustc_fs_util/src/lib.rs | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 0df1b243d69..7a883a13b72 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -1,6 +1,8 @@ -use std::ffi::CString; +use std::ffi::{CString, OsStr}; use std::path::{Path, PathBuf, absolute}; -use std::{fs, io}; +use std::{env, fs, io}; + +use tempfile::TempDir; // Unfortunately, on windows, it looks like msvcrt.dll is silently translating // verbatim paths under the hood to non-verbatim paths! This manifests itself as @@ -102,3 +104,43 @@ pub fn path_to_c_string(p: &Path) -> CString { pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { fs::canonicalize(&path).or_else(|_| absolute(&path)) } + +pub struct TempDirBuilder<'a, 'b> { + builder: tempfile::Builder<'a, 'b>, +} + +impl<'a, 'b> TempDirBuilder<'a, 'b> { + pub fn new() -> Self { + Self { builder: tempfile::Builder::new() } + } + + pub fn prefix<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self { + self.builder.prefix(prefix); + self + } + + pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self { + self.builder.suffix(suffix); + self + } + + pub fn tempdir_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<TempDir> { + let dir = dir.as_ref(); + // On Windows in CI, we had been getting fairly frequent "Access is denied" + // errors when creating temporary directories. + // So this implements a simple retry with backoff loop. + #[cfg(windows)] + for wait in 1..11 { + match self.builder.tempdir_in(dir) { + Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {} + t => return t, + } + std::thread::sleep(std::time::Duration::from_millis(1 << wait)); + } + self.builder.tempdir_in(dir) + } + + pub fn tempdir(&self) -> io::Result<TempDir> { + self.tempdir_in(env::temp_dir()) + } +} |
