2using System.Globalization;
6using System.Threading.Tasks;
8using Microsoft.Extensions.Hosting;
9using Microsoft.Extensions.Logging;
11using Mono.Unix.Native;
45 readonly ILogger<PosixProcessFeatures>
logger;
62 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
68 var result = Syscall.kill(process.Id, Signum.SIGCONT);
70 throw new UnixIOException(Stdlib.GetLastError());
76 var result = Syscall.kill(process.Id, Signum.SIGSTOP);
78 throw new UnixIOException(Stdlib.GetLastError());
83 =>
throw new NotSupportedException();
86 public async ValueTask
CreateDump(global::System.Diagnostics.Process process,
string outputFile,
bool minidump, CancellationToken cancellationToken)
88 ArgumentNullException.ThrowIfNull(process);
89 ArgumentNullException.ThrowIfNull(outputFile);
91 const string GCorePath =
"/usr/bin/gcore";
98 if (process.HasExited)
103 catch (InvalidOperationException ex)
112 Environment.CurrentDirectory,
113 $
"{(!minidump ? "-a
" : String.Empty)}-o {outputFile} {process.Id}",
115 readStandardHandles:
true,
116 noShellExecute:
true))
118 using (cancellationToken.Register(() => gcoreProc.Terminate()))
119 exitCode = (await gcoreProc.Lifetime).Value;
121 output = await gcoreProc.GetCombinedOutput(cancellationToken);
122 logger.LogDebug(
"gcore output:{newline}{output}", Environment.NewLine, output);
129 $
"Exit Code: {exitCode}{Environment.NewLine}Output:{Environment.NewLine}{output}"));
132 var generatedGCoreFile = $
"{outputFile}.{pid}";
137 public async ValueTask<int>
HandleProcessStart(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
139 ArgumentNullException.ThrowIfNull(process);
140 var pid = process.Id;
146 catch (
Exception ex) when (ex is not OperationCanceledException)
148 logger.LogWarning(ex,
"Failed to adjust OOM killer score for pid {pid}!", pid);
155 public async Task
StartAsync(CancellationToken cancellationToken)
158 string originalString;
163 "/proc/self/oom_score_adj");
164 using var reader =
new StreamReader(fileStream, Encoding.UTF8, leaveOpen:
true);
165 originalString = await reader.ReadToEndAsync(cancellationToken);
168 var trimmedString = originalString.Trim();
170 logger.LogTrace(
"Original oom_score_adj is \"{original}\"", trimmedString);
172 var originalOomAdjust = Int16.Parse(trimmedString, CultureInfo.InvariantCulture);
177 logger.LogWarning(
"oom_score_adj is at it's limit of 1000 (Clamped from {original}). TGS cannot guarantee the kill order of its parent/child processes!", originalOomAdjust);
179 logger.LogWarning(
"oom_score_adj is at it's limit of 1000. TGS cannot guarantee the kill order of its parent/child processes!");
186 catch (
Exception ex) when (ex is not OperationCanceledException)
188 logger.LogWarning(ex,
"Could not increase oom_score_adj!");
193 public Task
StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
206 var pidStr = pid.HasValue
207 ? pid.Value.ToString(CultureInfo.InvariantCulture)
210 "Setting oom_score_adj of {pid} to {adjustment}...", pidStr, adjustedValue);
212 $
"/proc/{pidStr}/oom_score_adj",
213 Encoding.UTF8.GetBytes(adjustedValue.ToString(CultureInfo.InvariantCulture)),
Operation exceptions thrown from the context of a Models.Job.
short baselineOomAdjust
The original value of oom_score_adj as read from the /proc/ filesystem. Inherited from parent process...
void SuspendProcess(global::System.Diagnostics.Process process)
Suspend a given process .
readonly IIOManager ioManager
The IIOManager for the PosixProcessFeatures.
readonly Lazy< IProcessExecutor > lazyLoadedProcessExecutor
Lazy<T> loaded IProcessExecutor.
async ValueTask< int > HandleProcessStart(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
Run events on starting a process. A ValueTask<TResult> resulting in the process ID.
async ValueTask CreateDump(global::System.Diagnostics.Process process, string outputFile, bool minidump, CancellationToken cancellationToken)
Create a dump file for a given process . A ValueTask representing the running operation.
void ResumeProcess(global::System.Diagnostics.Process process)
Resume a given suspended global::System.Diagnostics.Process.
const short ChildProcessOomAdjust
Difference from baselineOomAdjust to set the oom_score_adj of child processes to. 1 higher than ourse...
PosixProcessFeatures(Lazy< IProcessExecutor > lazyLoadedProcessExecutor, IIOManager ioManager, ILogger< PosixProcessFeatures > logger)
Initializes a new instance of the PosixProcessFeatures class.
const short SelfOomAdjust
Difference from baselineOomAdjust to set our own oom_score_adj to. 1 higher host watchdog.
ValueTask AdjustOutOfMemoryScore(int? pid, short adjustment, CancellationToken cancellationToken)
Set oom_score_adj for a given pid .
async Task StartAsync(CancellationToken cancellationToken)
readonly ILogger< PosixProcessFeatures > logger
The ILogger<TCategoryName> for the PosixProcessFeatures.
string GetExecutingUsername(global::System.Diagnostics.Process process)
Get the name of the user executing a given process . The name of the user executing process .
Task StopAsync(CancellationToken cancellationToken)
Interface for using filesystems.
FileStream CreateAsyncSequentialReadStream(string path)
Creates an asynchronous FileStream for sequential reading.
Task MoveFile(string source, string destination, CancellationToken cancellationToken)
Moves a file at source to destination .
ValueTask WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content.
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists.
Abstraction for suspending and resuming processes.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.