Skip to content

Commit 227b285

Browse files
Retry opening proc-macro DLLs a few times on Windows.
1 parent a9985cf commit 227b285

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

compiler/rustc_metadata/src/creader.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
3333
use proc_macro::bridge::client::ProcMacro;
3434
use std::ops::Fn;
3535
use std::path::Path;
36+
use std::time::Duration;
3637
use std::{cmp, env};
3738

3839
#[derive(Clone)]
@@ -689,8 +690,7 @@ impl<'a> CrateLoader<'a> {
689690
) -> Result<&'static [ProcMacro], CrateError> {
690691
// Make sure the path contains a / or the linker will search for it.
691692
let path = env::current_dir().unwrap().join(path);
692-
let lib = unsafe { libloading::Library::new(path) }
693-
.map_err(|err| CrateError::DlOpen(err.to_string()))?;
693+
let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?;
694694

695695
let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
696696
let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) }
@@ -1093,3 +1093,41 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
10931093
visit::walk_crate(&mut f, krate);
10941094
f.spans
10951095
}
1096+
1097+
// On Windows the compiler would sometimes intermittently fail to open the
1098+
// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
1099+
// system still holds a lock on the file, so we retry a few times before calling it
1100+
// an error.
1101+
fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
1102+
assert!(max_attempts > 0);
1103+
1104+
let mut last_error = None;
1105+
1106+
for attempt in 0..max_attempts {
1107+
match unsafe { libloading::Library::new(&path) } {
1108+
Ok(lib) => {
1109+
if attempt > 0 {
1110+
debug!(
1111+
"Loaded proc-macro `{}` after {} attempts.",
1112+
path.display(),
1113+
attempt + 1
1114+
);
1115+
}
1116+
return Ok(lib);
1117+
}
1118+
Err(err) => {
1119+
// Only try to recover from this specific error.
1120+
if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
1121+
return Err(err.to_string());
1122+
}
1123+
1124+
last_error = Some(err);
1125+
std::thread::sleep(Duration::from_millis(100));
1126+
debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
1127+
}
1128+
}
1129+
}
1130+
1131+
debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
1132+
Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts))
1133+
}

0 commit comments

Comments
 (0)