diff --git a/src/Tgstation.Server.Host/System/Process.cs b/src/Tgstation.Server.Host/System/Process.cs
index da67c8f0e8..210a86db8c 100644
--- a/src/Tgstation.Server.Host/System/Process.cs
+++ b/src/Tgstation.Server.Host/System/Process.cs
@@ -128,7 +128,7 @@ namespace Tgstation.Server.Host.System
///
public async ValueTask DisposeAsync()
{
- if (Interlocked.Exchange(ref disposed, 1) == 1)
+ if (Interlocked.Exchange(ref disposed, 1) != 0)
return;
logger.LogTrace("Disposing PID {pid}...", Id);
@@ -146,6 +146,7 @@ namespace Tgstation.Server.Host.System
///
public async ValueTask GetCombinedOutput(CancellationToken cancellationToken)
{
+ CheckDisposed();
if (readTask == null)
throw new InvalidOperationException("Output/Error stream reading was not enabled!");
@@ -158,7 +159,7 @@ namespace Tgstation.Server.Host.System
if (!readTask.IsCompleted)
{
logger.LogWarning("Detected process output read hang on PID {pid}! Closing handle as a workaround...", Id);
- await DisposeAsync();
+ cancellationTokenSource.Cancel();
}
}
@@ -168,6 +169,7 @@ namespace Tgstation.Server.Host.System
///
public void Terminate()
{
+ CheckDisposed();
if (handle.HasExited)
{
logger.LogTrace("PID {pid} already exited", Id);
@@ -190,6 +192,7 @@ namespace Tgstation.Server.Host.System
///
public void AdjustPriority(bool higher)
{
+ CheckDisposed();
var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal;
try
{
@@ -205,6 +208,7 @@ namespace Tgstation.Server.Host.System
///
public void Suspend()
{
+ CheckDisposed();
try
{
processFeatures.SuspendProcess(handle);
@@ -220,6 +224,7 @@ namespace Tgstation.Server.Host.System
///
public void Resume()
{
+ CheckDisposed();
try
{
processFeatures.ResumeProcess(handle);
@@ -235,6 +240,7 @@ namespace Tgstation.Server.Host.System
///
public string GetExecutingUsername()
{
+ CheckDisposed();
var result = processFeatures.GetExecutingUsername(handle);
logger.LogTrace("PID {pid} Username: {username}", Id, result);
return result;
@@ -244,6 +250,7 @@ namespace Tgstation.Server.Host.System
public ValueTask CreateDump(string outputFile, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(outputFile);
+ CheckDisposed();
logger.LogTrace("Dumping PID {pid} to {dumpFilePath}...", Id, outputFile);
return processFeatures.CreateDump(handle, outputFile, cancellationToken);
@@ -255,18 +262,29 @@ namespace Tgstation.Server.Host.System
/// A resulting in the or if the process was detached.
async Task WrapLifetimeTask()
{
+ bool hasExited;
try
{
await handle.WaitForExitAsync(cancellationTokenSource.Token);
- var exitCode = handle.ExitCode;
- logger.LogTrace("PID {pid} exited with code {exitCode}", Id, exitCode);
- return exitCode;
+ hasExited = true;
}
catch (OperationCanceledException ex)
{
logger.LogTrace(ex, "Process lifetime task cancelled!");
- return null;
+ hasExited = handle.HasExited;
}
+
+ if (!hasExited)
+ return null;
+
+ var exitCode = handle.ExitCode;
+ logger.LogTrace("PID {pid} exited with code {exitCode}", Id, exitCode);
+ return exitCode;
}
+
+ ///
+ /// Throws an if a method of the was called after .
+ ///
+ void CheckDisposed() => ObjectDisposedException.ThrowIf(disposed != 0, this);
}
}