@@ -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