@@ -33,6 +33,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
3333use  proc_macro:: bridge:: client:: ProcMacro ; 
3434use  std:: ops:: Fn ; 
3535use  std:: path:: Path ; 
36+ use  std:: time:: Duration ; 
3637use  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