Fixed plugin installation and endless plugin reloading on Linux (#924)
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-08-15 19:55:42 +02:00
1 parent 01f25b2bc0
commit 8148b66876
15 files changed
+402 -95

No files matched your search

@@ -290,7 +290,25 @@ public static partial class PluginFactory
return AVAILABLE_PLUGINS.Any(plugin => plugin.Id == configPluginId && plugin.Type is PluginType.CONFIGURATION && IsEnterpriseTestConfigurationPath(plugin.LocalPath));
}
private static async Task LockHotReloadAsync()
/// <summary>
/// Counts how many operations currently write to the plugins directory.
/// </summary>
/// <remarks>
/// Downloading an organization's configuration and installing a plugin can run at the same
/// time. Without counting, whichever finishes first would unlock hot reloading while the other
/// is still writing.
/// </remarks>
private static int HOT_RELOAD_LOCK_COUNT;
private static readonly SemaphoreSlim HOT_RELOAD_LOCK_SEMAPHORE = new(1, 1);
/// <summary>
/// Holds back hot reloading while the caller writes to the plugins directory.
/// </summary>
/// <remarks>
/// Every caller has to release the lock again, so wrap the write in a try-finally block. Hot
/// reloading resumes once the last caller has released it.
/// </remarks>
public static async Task LockHotReloadAsync()
{
if (!IsInitialized)
{
@@ -298,23 +316,28 @@ public static partial class PluginFactory
return;
}
await HOT_RELOAD_LOCK_SEMAPHORE.WaitAsync();
try
{
if (File.Exists(HOT_RELOAD_LOCK_FILE))
{
LOG.LogWarning("Hot reload lock file already exists.");
if (HOT_RELOAD_LOCK_COUNT++ > 0)
return;
}
await File.WriteAllTextAsync(HOT_RELOAD_LOCK_FILE, DateTime.UtcNow.ToString("o"));
}
catch (Exception e)
{
LOG.LogError(e, "An error occurred while trying to lock hot reloading.");
}
finally
{
HOT_RELOAD_LOCK_SEMAPHORE.Release();
}
}
private static void UnlockHotReload()
/// <summary>
/// Releases the hot reload lock of one caller, see LockHotReloadAsync.
/// </summary>
public static void UnlockHotReload()
{
if (!IsInitialized)
{
@@ -322,8 +345,20 @@ public static partial class PluginFactory
return;
}
HOT_RELOAD_LOCK_SEMAPHORE.Wait();
try
{
//
// The count can be zero when the reload gave up waiting and removed the lock file
// itself. We must not go negative, because that would keep the next lock from ever
// writing the file again:
//
if (HOT_RELOAD_LOCK_COUNT > 0)
HOT_RELOAD_LOCK_COUNT--;
if (HOT_RELOAD_LOCK_COUNT > 0)
return;
if(File.Exists(HOT_RELOAD_LOCK_FILE))
File.Delete(HOT_RELOAD_LOCK_FILE);
else
@@ -333,14 +368,19 @@ public static partial class PluginFactory
{
LOG.LogError(e, "An error occurred while trying to unlock hot reloading.");
}
finally
{
HOT_RELOAD_LOCK_SEMAPHORE.Release();
}
}
public static void Dispose()
{
if(!IsInitialized)
return;
HOT_RELOAD_WATCHER.Dispose();
HOT_RELOAD_DEBOUNCE_TIMER.Dispose();
}
public static IReadOnlyList<DataMandatoryInfo> GetMandatoryInfos()