Skip to content

Commit

Permalink
Code Quality: Pin WinRT server object to prevent object reference bei…
Browse files Browse the repository at this point in the history
…ng invalid (#15324)
  • Loading branch information
hez2010 committed May 7, 2024
1 parent d1853cb commit 8ed60f9
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 6 deletions.
12 changes: 11 additions & 1 deletion src/Files.App.Server/AppInstanceMonitor.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.Collections.Concurrent;
using System.Diagnostics;

namespace Files.App.Server;

public sealed class AppInstanceMonitor
{
private static int processCount = 0;
internal static ConcurrentDictionary<int, ConcurrentBag<IDisposable>> AppInstanceResources = new();

public static void StartMonitor(int processId)
{
Expand All @@ -19,10 +21,18 @@ public static void StartMonitor(int processId)

private static void Process_Exited(object? sender, EventArgs e)
{
if (sender is Process process)
if (sender is Process { Id: var processId } process)
{
process.Dispose();

if (AppInstanceResources.TryRemove(processId, out var instances))
{
foreach (var instance in instances)
{
instance.Dispose();
}
}

if (Interlocked.Decrement(ref processCount) == 0)
{
Program.ExitSignalEvent.Set();
Expand Down
34 changes: 33 additions & 1 deletion src/Files.App.Server/Database/FileTagsDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using LiteDB;
using Microsoft.Win32;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.ApplicationModel;
Expand All @@ -17,13 +18,16 @@

namespace Files.App.Server.Database
{
public sealed class FileTagsDatabase
public sealed class FileTagsDatabase : IDisposable
{
private readonly static string FileTagsKey = @$"Software\Files Community\{Package.Current.Id.FullName}\v1\FileTags";

private readonly static string FileTagsDbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "filetags.db");
private const string FileTagsCollectionName = "taggedfiles";

private readonly GCHandle _handle;
private bool _disposed = false;

static FileTagsDatabase()
{
if (File.Exists(FileTagsDbPath))
Expand All @@ -44,6 +48,25 @@ static FileTagsDatabase()
}
}

public FileTagsDatabase()
{
throw new NotSupportedException($"Instantiating {nameof(FileTagsDatabase)} by non-parameterized constructor is not supported.");
}

public FileTagsDatabase(int processId)
{
_handle = GCHandle.Alloc(this, GCHandleType.Pinned);

if (AppInstanceMonitor.AppInstanceResources.TryGetValue(processId, out var instances))
{
instances.Add(this);
}
else
{
AppInstanceMonitor.AppInstanceResources[processId] = [this];
}
}

private static void UpdateDb(LiteDatabase database)
{
if (database.UserVersion == 0)
Expand Down Expand Up @@ -279,5 +302,14 @@ private void IterateKeys(List<TaggedFile> list, string path, int depth)
IterateKeys(list, CombineKeys(path, subKey), depth + 1);
}
}

public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_handle.Free();
}
}
}
}
34 changes: 33 additions & 1 deletion src/Files.App.Server/Database/LayoutPreferencesDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using LiteDB;
using Microsoft.Win32;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.ApplicationModel;
using Windows.Storage;
using static Files.App.Server.Data.LayoutPreferencesRegistry;
Expand All @@ -13,13 +14,16 @@

namespace Files.App.Server.Database
{
public sealed class LayoutPreferencesDatabase
public sealed class LayoutPreferencesDatabase : IDisposable
{
private readonly static string LayoutSettingsKey = @$"Software\Files Community\{Package.Current.Id.FullName}\v1\LayoutPreferences";

private readonly static string LayoutSettingsDbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "user_settings.db");
private const string LayoutSettingsCollectionName = "layoutprefs";

private readonly GCHandle _handle;
private bool _disposed = false;

static LayoutPreferencesDatabase()
{
if (File.Exists(LayoutSettingsDbPath))
Expand All @@ -37,6 +41,25 @@ static LayoutPreferencesDatabase()
}
}

public LayoutPreferencesDatabase()
{
throw new NotSupportedException($"Instantiating {nameof(LayoutPreferencesDatabase)} by non-parameterized constructor is not supported.");
}

public LayoutPreferencesDatabase(int processId)
{
_handle = GCHandle.Alloc(this, GCHandleType.Pinned);

if (AppInstanceMonitor.AppInstanceResources.TryGetValue(processId, out var instances))
{
instances.Add(this);
}
else
{
AppInstanceMonitor.AppInstanceResources[processId] = [this];
}
}

public LayoutPreferencesItem? GetPreferences(string filePath, ulong? frn)
{
return FindPreferences(filePath, frn)?.LayoutPreferencesManager;
Expand Down Expand Up @@ -197,5 +220,14 @@ private void IterateKeys(List<LayoutPreferences> list, string path, int depth)

return null;
}

public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_handle.Free();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Files.App.Helpers
public class LayoutPreferencesDatabaseManager
{
// Fields
private readonly Server.Database.LayoutPreferencesDatabase _database = new();
private readonly Server.Database.LayoutPreferencesDatabase _database = new(Environment.ProcessId);

private DetailsLayoutColumnItem FromDatabaseEntity(Server.Data.ColumnPreferencesItem entry)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Files.App/Utils/FileTags/FileTagsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Files.App.Utils.FileTags
{
public static class FileTagsHelper
{
private static readonly Lazy<Server.Database.FileTagsDatabase> dbInstance = new(() => new());
private static readonly Server.Database.FileTagsDatabase dbInstance = new(Environment.ProcessId);

public static Server.Database.FileTagsDatabase GetDbInstance() => dbInstance.Value;
public static Server.Database.FileTagsDatabase GetDbInstance() => dbInstance;

public static string[] ReadFileTag(string filePath)
{
Expand Down

0 comments on commit 8ed60f9

Please sign in to comment.