mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-26 06:27:19 +01:00
Nullify ProcessExecutor
This commit is contained in:
@@ -29,7 +29,7 @@ namespace Tgstation.Server.Host.System
|
||||
/// the result of this function must be <see langword="await"/>ed before <see cref="IAsyncDisposable.DisposeAsync"/> is called.
|
||||
/// May call <see cref="IAsyncDisposable.DisposeAsync"/> internally if the process has exited.
|
||||
/// </remarks>
|
||||
ValueTask<string> GetCombinedOutput(CancellationToken cancellationToken);
|
||||
ValueTask<string?> GetCombinedOutput(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Asycnhronously terminates the process.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
IProcess LaunchProcess(
|
||||
string fileName,
|
||||
string workingDirectory,
|
||||
string? arguments = null,
|
||||
string arguments,
|
||||
string? fileRedirect = null,
|
||||
bool readStandardHandles = false,
|
||||
bool noShellExecute = false);
|
||||
@@ -34,13 +34,13 @@
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="IProcess.Id"/>.</param>
|
||||
/// <returns>The <see cref="IProcess"/> represented by <paramref name="id"/> on success, <see langword="null"/> on failure.</returns>
|
||||
IProcess GetProcess(int id);
|
||||
IProcess? GetProcess(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Get a <see cref="IProcess"/> with a given <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the process executable without the extension.</param>
|
||||
/// <returns>The <see cref="IProcess"/> represented by <paramref name="name"/> on success, <see langword="null"/> on failure.</returns>
|
||||
IProcess GetProcessByName(string name);
|
||||
IProcess? GetProcessByName(string name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Tgstation.Server.Host.System
|
||||
throw new JobException(ErrorCode.GameServerOffline, ex);
|
||||
}
|
||||
|
||||
string output;
|
||||
string? output;
|
||||
int exitCode;
|
||||
await using (var gcoreProc = lazyLoadedProcessExecutor.Value.LaunchProcess(
|
||||
GCorePath,
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.System
|
||||
/// <summary>
|
||||
/// The <see cref="Task{TResult}"/> resulting in the process' standard output/error text.
|
||||
/// </summary>
|
||||
readonly Task<string> readTask;
|
||||
readonly Task<string?>? readTask;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Process"/> was disposed.
|
||||
@@ -78,8 +78,8 @@ namespace Tgstation.Server.Host.System
|
||||
IProcessFeatures processFeatures,
|
||||
IAsyncDelayer asyncDelayer,
|
||||
global::System.Diagnostics.Process handle,
|
||||
CancellationTokenSource readerCts,
|
||||
Task<string> readTask,
|
||||
CancellationTokenSource? readerCts,
|
||||
Task<string?>? readTask,
|
||||
ILogger<Process> logger,
|
||||
bool preExisting)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ namespace Tgstation.Server.Host.System
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<string> GetCombinedOutput(CancellationToken cancellationToken)
|
||||
public async ValueTask<string?> GetCombinedOutput(CancellationToken cancellationToken)
|
||||
{
|
||||
if (readTask == null)
|
||||
throw new InvalidOperationException("Output/Error stream reading was not enabled!");
|
||||
|
||||
@@ -9,8 +9,6 @@ using Microsoft.Extensions.Logging;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Utils;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tgstation.Server.Host.System
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -86,7 +84,7 @@ namespace Tgstation.Server.Host.System
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IProcess GetProcess(int id)
|
||||
public IProcess? GetProcess(int id)
|
||||
{
|
||||
logger.LogDebug("Attaching to process {pid}...", id);
|
||||
global::System.Diagnostics.Process handle;
|
||||
@@ -116,7 +114,7 @@ namespace Tgstation.Server.Host.System
|
||||
string fileName,
|
||||
string workingDirectory,
|
||||
string arguments,
|
||||
string fileRedirect,
|
||||
string? fileRedirect,
|
||||
bool readStandardHandles,
|
||||
bool noShellExecute)
|
||||
{
|
||||
@@ -143,11 +141,11 @@ namespace Tgstation.Server.Host.System
|
||||
|
||||
handle.StartInfo.UseShellExecute = !noShellExecute;
|
||||
|
||||
Task<string> readTask = null;
|
||||
CancellationTokenSource disposeCts = null;
|
||||
Task<string?>? readTask = null;
|
||||
CancellationTokenSource? disposeCts = null;
|
||||
try
|
||||
{
|
||||
TaskCompletionSource processStartTcs = null;
|
||||
TaskCompletionSource? processStartTcs = null;
|
||||
if (readStandardHandles)
|
||||
{
|
||||
processStartTcs = new TaskCompletionSource();
|
||||
@@ -203,11 +201,11 @@ namespace Tgstation.Server.Host.System
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IProcess GetProcessByName(string name)
|
||||
public IProcess? GetProcessByName(string name)
|
||||
{
|
||||
logger.LogTrace("GetProcessByName: {processName}...", name ?? throw new ArgumentNullException(nameof(name)));
|
||||
var procs = global::System.Diagnostics.Process.GetProcessesByName(name);
|
||||
global::System.Diagnostics.Process handle = null;
|
||||
global::System.Diagnostics.Process? handle = null;
|
||||
foreach (var proc in procs)
|
||||
if (handle == null)
|
||||
handle = proc;
|
||||
@@ -231,7 +229,7 @@ namespace Tgstation.Server.Host.System
|
||||
/// <param name="fileRedirect">The optional path to redirect the streams to.</param>
|
||||
/// <param name="disposeToken">The <see cref="CancellationToken"/> that triggers when the <see cref="Process"/> is disposed.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the program's output/error text if <paramref name="fileRedirect"/> is <see langword="null"/>, <see langword="null"/> otherwise.</returns>
|
||||
async Task<string> ConsumeReaders(global::System.Diagnostics.Process handle, Task startTask, string fileRedirect, CancellationToken disposeToken)
|
||||
async Task<string?> ConsumeReaders(global::System.Diagnostics.Process handle, Task startTask, string? fileRedirect, CancellationToken disposeToken)
|
||||
{
|
||||
await startTask;
|
||||
|
||||
@@ -241,9 +239,9 @@ namespace Tgstation.Server.Host.System
|
||||
// once we obtain these handles we're responsible for them
|
||||
using var stdOutHandle = handle.StandardOutput;
|
||||
using var stdErrHandle = handle.StandardError;
|
||||
Task<string> outputReadTask = null, errorReadTask = null;
|
||||
Task<string?>? outputReadTask = null, errorReadTask = null;
|
||||
bool outputOpen = true, errorOpen = true;
|
||||
async Task<string> GetNextLine()
|
||||
async Task<string?> GetNextLine()
|
||||
{
|
||||
if (outputOpen && outputReadTask == null)
|
||||
outputReadTask = stdOutHandle.ReadLineAsync(disposeToken).AsTask();
|
||||
@@ -251,7 +249,7 @@ namespace Tgstation.Server.Host.System
|
||||
if (errorOpen && errorReadTask == null)
|
||||
errorReadTask = stdErrHandle.ReadLineAsync(disposeToken).AsTask();
|
||||
|
||||
var completedTask = await Task.WhenAny(outputReadTask ?? errorReadTask, errorReadTask ?? outputReadTask);
|
||||
var completedTask = await Task.WhenAny(outputReadTask ?? errorReadTask!, errorReadTask ?? outputReadTask!);
|
||||
var line = await completedTask;
|
||||
if (completedTask == outputReadTask)
|
||||
{
|
||||
@@ -275,7 +273,7 @@ namespace Tgstation.Server.Host.System
|
||||
await using var fileStream = fileRedirect != null ? ioManager.CreateAsyncSequentialWriteStream(fileRedirect) : null;
|
||||
await using var writer = fileStream != null ? new StreamWriter(fileStream) : null;
|
||||
|
||||
string text;
|
||||
string? text;
|
||||
var stringBuilder = fileStream == null ? new StringBuilder() : null;
|
||||
try
|
||||
{
|
||||
@@ -283,11 +281,11 @@ namespace Tgstation.Server.Host.System
|
||||
{
|
||||
if (fileStream != null)
|
||||
{
|
||||
await writer.WriteLineAsync(text.AsMemory(), disposeToken);
|
||||
await writer!.WriteLineAsync(text.AsMemory(), disposeToken);
|
||||
await writer.FlushAsync(disposeToken);
|
||||
}
|
||||
else
|
||||
stringBuilder.AppendLine(text);
|
||||
stringBuilder!.AppendLine(text);
|
||||
}
|
||||
|
||||
logger.LogTrace("Finished read for PID {pid}", pid);
|
||||
@@ -296,7 +294,7 @@ namespace Tgstation.Server.Host.System
|
||||
{
|
||||
logger.LogWarning(ex, "PID {pid} stream reading interrupted!", pid);
|
||||
if (fileStream != null)
|
||||
await writer.WriteLineAsync("-- Process detached, log truncated. This is likely due a to TGS restart --");
|
||||
await writer!.WriteLineAsync("-- Process detached, log truncated. This is likely due a to TGS restart --");
|
||||
}
|
||||
|
||||
return stringBuilder?.ToString();
|
||||
|
||||
Reference in New Issue
Block a user