Skip to content

Commit 85919bb

Browse files
[Java.Interop.Tools.Cecil] Fix retry logic in ReadAssembly() to skip symbol loading (#1401)
The retry in `ReadAssembly` sets `reader_parameters.ReadSymbols = false`, but `LoadFromMemoryMappedFile` checks the instance field `loadDebugSymbols` instead, so the retry re-opens the same locked PDB file and throws the same `IOException`. Fix by passing an explicit `loadSymbols` parameter to `LoadFromMemoryMappedFile` so the retry can actually skip symbol loading. When `loadDebugSymbols` is false, rethrow immediately since there is nothing to retry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c7b4ea6 commit 85919bb

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/DirectoryAssemblyResolver.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,34 +162,36 @@ protected virtual AssemblyDefinition ReadAssembly (string file)
162162
SymbolReaderProvider = loadReaderParameters.SymbolReaderProvider,
163163
};
164164
try {
165-
return LoadFromMemoryMappedFile (file, reader_parameters);
165+
return LoadFromMemoryMappedFile (file, reader_parameters, loadDebugSymbols);
166166
} catch (Exception ex) {
167+
if (!loadDebugSymbols)
168+
throw;
167169
logger (
168170
TraceLevel.Verbose,
169171
$"Failed to read '{file}' with debugging symbols. Retrying to load it without it. Error details are logged below.");
170172
logger (TraceLevel.Verbose, ex.ToString ());
171173
reader_parameters.ReadSymbols = false;
172-
return LoadFromMemoryMappedFile (file, reader_parameters);
174+
return LoadFromMemoryMappedFile (file, reader_parameters, loadSymbols: false);
173175
} finally {
174176
reader_parameters.SymbolStream?.Dispose ();
175177
}
176178
}
177179

178-
AssemblyDefinition LoadFromMemoryMappedFile (string file, ReaderParameters options)
180+
AssemblyDefinition LoadFromMemoryMappedFile (string file, ReaderParameters options, bool loadSymbols)
179181
{
180182
// We can't use MemoryMappedFile when ReadWrite is true
181183
if (options.ReadWrite) {
182-
if (loadDebugSymbols) {
184+
if (loadSymbols) {
183185
LoadSymbols (file, options, File.OpenRead);
184186
}
185187
return AssemblyDefinition.ReadAssembly (file, options);
186188
}
187189

188190
// We know the capacity for disposables
189191
var disposables = new List<IDisposable> (
190-
(1 + (loadDebugSymbols ? 1 : 0)) * OpenMemoryMappedViewStream_disposables_Add_calls);
192+
(1 + (loadSymbols ? 1 : 0)) * OpenMemoryMappedViewStream_disposables_Add_calls);
191193
try {
192-
if (loadDebugSymbols) {
194+
if (loadSymbols) {
193195
LoadSymbols (file, options, f => OpenMemoryMappedViewStream (f, disposables));
194196
}
195197

tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/DirectoryAssemblyResolverTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,21 @@ public void LoadSymbols ([Values (true, false)] bool loadDebugSymbols, [Values (
4949
Assert.IsNotNull (assembly);
5050
Assert.AreEqual (loadDebugSymbols, assembly.MainModule.HasSymbols);
5151
}
52+
53+
[Test]
54+
public void LoadSymbols_LockedPdb ([Values (true, false)] bool readWrite)
55+
{
56+
// Lock the PDB file exclusively so LoadSymbols will fail with IOException
57+
using var lockStream = new FileStream (symbol_path, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
58+
59+
using var resolver = new DirectoryAssemblyResolver (Log, loadDebugSymbols: true, new ReaderParameters {
60+
ReadWrite = readWrite
61+
});
62+
63+
// Should succeed by retrying without symbols instead of throwing
64+
var assembly = resolver.Load (assembly_path);
65+
Assert.IsNotNull (assembly);
66+
Assert.IsFalse (assembly.MainModule.HasSymbols);
67+
}
5268
}
5369
}

0 commit comments

Comments
 (0)