Skip to content

Commit

Permalink
BUGFIX: make caches of file services and resolvers thread-safe.
Browse files Browse the repository at this point in the history
  • Loading branch information
Washi1337 committed Nov 15, 2023
1 parent f961609 commit 61b6ddf
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 34 deletions.
23 changes: 14 additions & 9 deletions src/AsmResolver.DotNet/AssemblyResolverBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using AsmResolver.DotNet.Signatures;
Expand All @@ -15,7 +16,7 @@ public abstract class AssemblyResolverBase : IAssemblyResolver
private static readonly string[] BinaryFileExtensions = {".dll", ".exe"};
private static readonly SignatureComparer Comparer = new(SignatureComparisonFlags.AcceptNewerVersions);

private readonly Dictionary<AssemblyDescriptor, AssemblyDefinition> _cache = new(new SignatureComparer());
private readonly ConcurrentDictionary<AssemblyDescriptor, AssemblyDefinition> _cache = new(new SignatureComparer());

/// <summary>
/// Initializes the base of an assembly resolver.
Expand Down Expand Up @@ -46,14 +47,18 @@ public IList<string> SearchDirectories
/// <inheritdoc />
public AssemblyDefinition? Resolve(AssemblyDescriptor assembly)
{
if (_cache.TryGetValue(assembly, out var assemblyDef))
return assemblyDef;
AssemblyDefinition? result;

assemblyDef = ResolveImpl(assembly);
if (assemblyDef is not null)
_cache.Add(assembly, assemblyDef);
while (!_cache.TryGetValue(assembly, out result))
{
var candidate = ResolveImpl(assembly);
if (candidate is null)
break;

return assemblyDef;
_cache.TryAdd(assembly, candidate);
}

return result;
}

/// <inheritdoc />
Expand All @@ -65,11 +70,11 @@ public void AddToCache(AssemblyDescriptor descriptor, AssemblyDefinition definit
if (!Comparer.Equals(descriptor, definition))
throw new ArgumentException("Assembly descriptor and definition do not refer to the same assembly.");

_cache.Add(descriptor, definition);
_cache.TryAdd(descriptor, definition);
}

/// <inheritdoc />
public bool RemoveFromCache(AssemblyDescriptor descriptor) => _cache.Remove(descriptor);
public bool RemoveFromCache(AssemblyDescriptor descriptor) => _cache.TryRemove(descriptor, out _);

/// <inheritdoc />
public bool HasCached(AssemblyDescriptor descriptor) => _cache.ContainsKey(descriptor);
Expand Down
14 changes: 4 additions & 10 deletions src/AsmResolver/IO/ByteArrayFileService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;

namespace AsmResolver.IO
{
Expand All @@ -11,25 +11,19 @@ namespace AsmResolver.IO
/// </summary>
public class ByteArrayFileService : IFileService
{
private readonly Dictionary<string, ByteArrayInputFile> _files = new();
private readonly ConcurrentDictionary<string, ByteArrayInputFile> _files = new();

/// <inheritdoc />
public IEnumerable<string> GetOpenedFiles() => _files.Keys;

/// <inheritdoc />
public IInputFile OpenFile(string filePath)
{
if (!_files.TryGetValue(filePath, out var file))
{
file = new ByteArrayInputFile(filePath);
_files.Add(filePath, file);
}

return file;
return _files.GetOrAdd(filePath, x => new ByteArrayInputFile(x));
}

/// <inheritdoc />
public void InvalidateFile(string filePath) => _files.Remove(filePath);
public void InvalidateFile(string filePath) => _files.TryRemove(filePath, out _);

/// <inheritdoc />
void IDisposable.Dispose() => _files.Clear();
Expand Down
17 changes: 5 additions & 12 deletions src/AsmResolver/IO/MemoryMappedFileService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace AsmResolver.IO
{
Expand All @@ -8,31 +10,22 @@ namespace AsmResolver.IO
/// </summary>
public class MemoryMappedFileService : IFileService
{
private readonly Dictionary<string, MemoryMappedInputFile> _files = new();
private readonly ConcurrentDictionary<string, MemoryMappedInputFile> _files = new();

/// <inheritdoc />
public IEnumerable<string> GetOpenedFiles() => _files.Keys;

/// <inheritdoc />
public IInputFile OpenFile(string filePath)
{
if (!_files.TryGetValue(filePath, out var file))
{
file = new MemoryMappedInputFile(filePath);
_files.Add(filePath, file);
}

return file;
return _files.GetOrAdd(filePath, x => new MemoryMappedInputFile(x));
}

/// <inheritdoc />
public void InvalidateFile(string filePath)
{
if (_files.TryGetValue(filePath, out var file))
{
if (_files.TryRemove(filePath, out var file))
file.Dispose();
_files.Remove(filePath);
}
}

/// <inheritdoc />
Expand Down
4 changes: 2 additions & 2 deletions src/AsmResolver/IO/MemoryMappedInputFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public BinaryStreamReader CreateReader(ulong address, uint rva, uint length) =>
/// <inheritdoc />
public void Dispose()
{
_file?.Dispose();
_dataSource?.Dispose();
_file.Dispose();
_dataSource.Dispose();
}
}
}
1 change: 0 additions & 1 deletion src/AsmResolver/IO/UncachedFileService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace AsmResolver.IO
Expand Down

0 comments on commit 61b6ddf

Please sign in to comment.