diff --git a/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/DirectoryAssemblyResolver.cs b/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/DirectoryAssemblyResolver.cs index aeaaa6113..0fd3c37e5 100644 --- a/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/DirectoryAssemblyResolver.cs +++ b/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/DirectoryAssemblyResolver.cs @@ -162,24 +162,26 @@ protected virtual AssemblyDefinition ReadAssembly (string file) SymbolReaderProvider = loadReaderParameters.SymbolReaderProvider, }; try { - return LoadFromMemoryMappedFile (file, reader_parameters); + return LoadFromMemoryMappedFile (file, reader_parameters, loadDebugSymbols); } catch (Exception ex) { + if (!loadDebugSymbols) + throw; logger ( TraceLevel.Verbose, $"Failed to read '{file}' with debugging symbols. Retrying to load it without it. Error details are logged below."); logger (TraceLevel.Verbose, ex.ToString ()); reader_parameters.ReadSymbols = false; - return LoadFromMemoryMappedFile (file, reader_parameters); + return LoadFromMemoryMappedFile (file, reader_parameters, loadSymbols: false); } finally { reader_parameters.SymbolStream?.Dispose (); } } - AssemblyDefinition LoadFromMemoryMappedFile (string file, ReaderParameters options) + AssemblyDefinition LoadFromMemoryMappedFile (string file, ReaderParameters options, bool loadSymbols) { // We can't use MemoryMappedFile when ReadWrite is true if (options.ReadWrite) { - if (loadDebugSymbols) { + if (loadSymbols) { LoadSymbols (file, options, File.OpenRead); } return AssemblyDefinition.ReadAssembly (file, options); @@ -187,9 +189,9 @@ AssemblyDefinition LoadFromMemoryMappedFile (string file, ReaderParameters optio // We know the capacity for disposables var disposables = new List ( - (1 + (loadDebugSymbols ? 1 : 0)) * OpenMemoryMappedViewStream_disposables_Add_calls); + (1 + (loadSymbols ? 1 : 0)) * OpenMemoryMappedViewStream_disposables_Add_calls); try { - if (loadDebugSymbols) { + if (loadSymbols) { LoadSymbols (file, options, f => OpenMemoryMappedViewStream (f, disposables)); } diff --git a/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/DirectoryAssemblyResolverTests.cs b/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/DirectoryAssemblyResolverTests.cs index 7053476d7..c2d48837f 100644 --- a/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/DirectoryAssemblyResolverTests.cs +++ b/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/DirectoryAssemblyResolverTests.cs @@ -49,5 +49,21 @@ public void LoadSymbols ([Values (true, false)] bool loadDebugSymbols, [Values ( Assert.IsNotNull (assembly); Assert.AreEqual (loadDebugSymbols, assembly.MainModule.HasSymbols); } + + [Test] + public void LoadSymbols_LockedPdb ([Values (true, false)] bool readWrite) + { + // Lock the PDB file exclusively so LoadSymbols will fail with IOException + using var lockStream = new FileStream (symbol_path, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + + using var resolver = new DirectoryAssemblyResolver (Log, loadDebugSymbols: true, new ReaderParameters { + ReadWrite = readWrite + }); + + // Should succeed by retrying without symbols instead of throwing + var assembly = resolver.Load (assembly_path); + Assert.IsNotNull (assembly); + Assert.IsFalse (assembly.MainModule.HasSymbols); + } } }