tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
PosixSignalHandler.cs
Go to the documentation of this file.
1using System;
2using System.Threading;
3using System.Threading.Tasks;
4
5using Microsoft.Extensions.Hosting;
6using Microsoft.Extensions.Logging;
7using Mono.Unix;
8using Mono.Unix.Native;
9
12
14{
19 {
23 const int CheckDelayMs = 250;
24
29
34
38 readonly ILogger<PosixSignalHandler> logger;
39
43 readonly CancellationTokenSource cancellationTokenSource;
44
49
57 {
58 this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
59 this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
60 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
61
62 cancellationTokenSource = new CancellationTokenSource();
63 }
64
66 public void Dispose() => cancellationTokenSource.Dispose();
67
69 public Task StartAsync(CancellationToken cancellationToken)
70 {
71 if (signalCheckerTask != null)
72 throw new InvalidOperationException("Attempted to start PosixSignalHandler twice!");
73
74 signalCheckerTask = Task.WhenAll(
75 SignalChecker(Signum.SIGUSR1, false),
76 SignalChecker(Signum.SIGUSR2, true));
77
78 return Task.CompletedTask;
79 }
80
82 public async Task StopAsync(CancellationToken cancellationToken)
83 {
84 if (signalCheckerTask?.IsCompleted != false)
85 return;
86
87 logger.LogDebug("Stopping SignalCheckerThread...");
89
90 logger.LogTrace("Joining SignalCheckerThread...");
92 }
93
100 async Task SignalChecker(Signum signum, bool detach)
101 {
102 try
103 {
104 logger.LogTrace("Started SignalChecker");
105
106 using var unixSignal = new UnixSignal(signum);
107 if (!unixSignal.IsSet)
108 {
109 logger.LogTrace("Waiting for {signum}...", signum);
110 var cancellationToken = cancellationTokenSource.Token;
111 while (!unixSignal.IsSet)
112 await asyncDelayer.Delay(TimeSpan.FromMilliseconds(CheckDelayMs), cancellationToken);
113
114 logger.LogTrace("{signum} received!", signum);
115 }
116 else
117 logger.LogDebug("{signum} has already been sent", signum);
118
119 logger.LogTrace("Triggering graceful shutdown...");
120 await serverControl.GracefulShutdown(detach);
121 }
122 catch (OperationCanceledException ex)
123 {
124 logger.LogDebug(ex, "SignalChecker cancelled!");
125 }
126 catch (Exception ex)
127 {
128 logger.LogError(ex, "SignalChecker crashed!");
129 }
130 finally
131 {
132 logger.LogTrace("Exiting SignalChecker...");
133 }
134 }
135 }
136}
Task StartAsync(CancellationToken cancellationToken)
Task? signalCheckerTask
The thread used to check the signal. See http://docs.go-mono.com/?link=T%3aMono.Unix....
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource used to stop the signalCheckerTask.
const int CheckDelayMs
Check for signals each time this amount of milliseconds pass.
PosixSignalHandler(IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< PosixSignalHandler > logger)
Initializes a new instance of the PosixSignalHandler class.
async Task SignalChecker(Signum signum, bool detach)
Thread for listening to signal.
readonly ILogger< PosixSignalHandler > logger
The ILogger for the PosixSignalHandler.
async Task StopAsync(CancellationToken cancellationToken)
readonly IServerControl serverControl
The IServerControl for the PosixSignalHandler.
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the PosixSignalHandler.
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
ValueTask GracefulShutdown(bool detach)
Gracefully shutsdown the Host.
ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .