50 lines
1.5 KiB
C#
50 lines
1.5 KiB
C#
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Zcbot.WindowsNode;
|
|
|
|
internal sealed class ProcessSupervisor
|
|
{
|
|
internal Process Start(
|
|
ProcessStartInfo startInfo,
|
|
string failureMessage = "Adapter worker did not start.") =>
|
|
Process.Start(startInfo)
|
|
?? throw new InvalidOperationException(failureMessage);
|
|
|
|
internal async Task TerminateTreeAsync(
|
|
Process process,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (process.HasExited) return;
|
|
process.Kill(entireProcessTree: true);
|
|
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
|
timeout.CancelAfter(TimeSpan.FromSeconds(30));
|
|
try
|
|
{
|
|
await process.WaitForExitAsync(timeout.Token);
|
|
}
|
|
catch (OperationCanceledException exception) when (!cancellationToken.IsCancellationRequested)
|
|
{
|
|
throw new InvalidOperationException(
|
|
"Adapter worker process tree did not terminate within 30 seconds.", exception);
|
|
}
|
|
}
|
|
|
|
internal async Task<string> CaptureOutputAsync(
|
|
StreamReader reader,
|
|
IProgress<string>? progress = null)
|
|
{
|
|
var output = new StringBuilder();
|
|
while (await reader.ReadLineAsync() is { } line)
|
|
{
|
|
if (output.Length < 16 * 1024)
|
|
{
|
|
output.AppendLine(line);
|
|
}
|
|
progress?.Report(line);
|
|
}
|
|
return output.ToString();
|
|
}
|
|
}
|