From da78b8e8a15b3cb059bab11f6012e1cebfebf5c8 Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Sun, 3 Dec 2023 14:53:45 -0500 Subject: [PATCH] Fix deadlock with `DumpOnHealthCheckRestart` --- .../Components/Watchdog/WatchdogBase.cs | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs index 59aebe0c57..60b3deb05f 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs @@ -446,29 +446,8 @@ namespace Tgstation.Server.Host.Components.Watchdog /// public async ValueTask CreateDump(CancellationToken cancellationToken) { - const string DumpDirectory = "ProcessDumps"; using (await SemaphoreSlimContext.Lock(synchronizationSemaphore, cancellationToken)) - { - var dumpFileNameTemplate = diagnosticsIOManager.ResolvePath( - diagnosticsIOManager.ConcatPath( - DumpDirectory, - $"DreamDaemon-{DateTimeOffset.UtcNow.ToFileStamp()}.dmp")); - - var dumpFileName = dumpFileNameTemplate; - var iteration = 0; - while (await diagnosticsIOManager.FileExists(dumpFileName, cancellationToken)) - dumpFileName = $"{dumpFileNameTemplate} ({++iteration})"; - - if (iteration == 0) - await diagnosticsIOManager.CreateDirectory(DumpDirectory, cancellationToken); - - var session = GetActiveController(); - if (session?.Lifetime.IsCompleted != false) - throw new JobException(ErrorCode.GameServerOffline); - - Logger.LogInformation("Dumping session to {dumpFileName}...", dumpFileName); - await session.CreateDump(dumpFileName, cancellationToken); - } + await CreateDumpNoLock(cancellationToken); } /// @@ -1153,7 +1132,7 @@ namespace Tgstation.Server.Host.Components.Watchdog Logger.LogDebug("DumpOnHealthCheckRestart enabled."); try { - await CreateDump(cancellationToken); + await CreateDumpNoLock(cancellationToken); } catch (JobException ex) { @@ -1203,5 +1182,34 @@ namespace Tgstation.Server.Host.Components.Watchdog .Where(nullableChannelId => nullableChannelId.HasValue) .Select(nullableChannelId => nullableChannelId.Value)); } + + /// + /// Attempt to create a process dump for the game server. Requires a lock on . + /// + /// The for the operation. + /// A representing the running operation. + async ValueTask CreateDumpNoLock(CancellationToken cancellationToken) + { + const string DumpDirectory = "ProcessDumps"; + var dumpFileNameTemplate = diagnosticsIOManager.ResolvePath( + diagnosticsIOManager.ConcatPath( + DumpDirectory, + $"DreamDaemon-{DateTimeOffset.UtcNow.ToFileStamp()}.dmp")); + + var dumpFileName = dumpFileNameTemplate; + var iteration = 0; + while (await diagnosticsIOManager.FileExists(dumpFileName, cancellationToken)) + dumpFileName = $"{dumpFileNameTemplate} ({++iteration})"; + + if (iteration == 0) + await diagnosticsIOManager.CreateDirectory(DumpDirectory, cancellationToken); + + var session = GetActiveController(); + if (session?.Lifetime.IsCompleted != false) + throw new JobException(ErrorCode.GameServerOffline); + + Logger.LogInformation("Dumping session to {dumpFileName}...", dumpFileName); + await session.CreateDump(dumpFileName, cancellationToken); + } } }