Skip to content

Commit

Permalink
v1 of systemd service management
Browse files Browse the repository at this point in the history
  • Loading branch information
PJB3005 committed Sep 10, 2023
1 parent d603d89 commit 2cdd942
Show file tree
Hide file tree
Showing 11 changed files with 19,887 additions and 32 deletions.
82 changes: 78 additions & 4 deletions SS14.Watchdog/Components/ProcessManagement/IProcessManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,86 @@ public sealed record ProcessStartData(
/// </summary>
public interface IProcessHandle
{
bool HasExited { get; }
int ExitCode { get; }

void DumpProcess(string file, DumpType type);

Task WaitForExitAsync(CancellationToken cancel = default);

void Kill();
Task Kill();

Task<ProcessExitStatus?> GetExitStatusAsync();
}

/// <summary>
/// Status for how a process has exited.
/// </summary>
/// <param name="Reason">The reason why the process exited. Check the enum for possible values.</param>
/// <param name="Status">
/// Reason-specific value.
/// For <see cref="ProcessExitReason.ExitCode"/> this is the exit code.
/// For <see cref="ProcessExitReason.Signal"/> and <see cref="ProcessExitReason.CoreDumped"/> this is the signal that killed the process.
/// </param>
/// <seealso cref="IProcessHandle"/>
public sealed record ProcessExitStatus(ProcessExitReason Reason, int Status)
{
public ProcessExitStatus(ProcessExitReason reason) : this(reason, 0)
{
}

public bool IsClean => Reason == ProcessExitReason.ExitCode && Status == 0 || Reason == ProcessExitReason.Success;
}

/// <summary>
/// Reason values for <see cref="ProcessExitStatus"/>.
/// </summary>
public enum ProcessExitReason
{
// These somewhat correspond to systemd's values for "Result" on a Service, kinda.
// https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html#Properties2

/// <summary>
/// Process exited "successfully" according to systemd.
/// </summary>
/// <remarks>
/// This probably means exit code 0, but I want to distinguish them as technically they're not equal.
/// </remarks>
Success,

/// <summary>
/// Process exited recorded exit code.
/// </summary>
ExitCode,

/// <summary>
/// Process was killed by uncaught signal.
/// </summary>
/// <remarks>
/// This won't apply if the process is killed with SIGTERM,
/// as the game handles that and manually returns exit code signum + 128.
/// </remarks>
Signal,

/// <summary>
/// Process crashed and dumped core.
/// </summary>
CoreDump,

/// <summary>
/// Systemd operation failed.
/// </summary>
SystemdFailed,

/// <summary>
/// Timeout executing service operation.
/// </summary>
Timeout,

/// <summary>
/// Process was killed by the Linux OOM killer.
/// </summary>
OomKill,

/// <summary>
/// Catch-all for other unhandled status codes.
/// </summary>
Other,
}
16 changes: 12 additions & 4 deletions SS14.Watchdog/Components/ProcessManagement/ProcessManagerBasic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ private sealed class Handle : IProcessHandle
{
private readonly Process _process;

public bool HasExited => _process.HasExited;
public int ExitCode => _process.ExitCode;

public Handle(Process process)
{
_process = process;
Expand All @@ -187,9 +184,20 @@ public async Task WaitForExitAsync(CancellationToken cancel = default)
await _process.WaitForExitAsync(cancel);
}

public void Kill()
public Task<ProcessExitStatus?> GetExitStatusAsync()
{
if (!_process.HasExited)
return Task.FromResult<ProcessExitStatus?>(null);

var code = _process.ExitCode;
return Task.FromResult<ProcessExitStatus?>(new ProcessExitStatus(ProcessExitReason.ExitCode, code));
}

public Task Kill()
{
_process.Kill(entireProcessTree: true);

return Task.CompletedTask;
}
}
}
Loading

0 comments on commit 2cdd942

Please sign in to comment.