@@ -33,6 +33,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
33
33
use proc_macro:: bridge:: client:: ProcMacro ;
34
34
use std:: ops:: Fn ;
35
35
use std:: path:: Path ;
36
+ use std:: time:: Duration ;
36
37
use std:: { cmp, env} ;
37
38
38
39
#[ derive( Clone ) ]
@@ -689,8 +690,7 @@ impl<'a> CrateLoader<'a> {
689
690
) -> Result < & ' static [ ProcMacro ] , CrateError > {
690
691
// Make sure the path contains a / or the linker will search for it.
691
692
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) ) ?;
694
694
695
695
let sym_name = self . sess . generate_proc_macro_decls_symbol ( stable_crate_id) ;
696
696
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> {
1093
1093
visit:: walk_crate ( & mut f, krate) ;
1094
1094
f. spans
1095
1095
}
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