2using System.Collections.Generic;
3using System.Globalization;
8using System.Threading.Tasks;
10using Microsoft.Extensions.Hosting;
11using Microsoft.Extensions.Logging;
13using Mono.Unix.Native;
47 readonly ILogger<PosixProcessFeatures>
logger;
64 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
70 var result = Syscall.kill(process.Id, Signum.SIGCONT);
72 throw new UnixIOException(Stdlib.GetLastError());
78 var result = Syscall.kill(process.Id, Signum.SIGSTOP);
80 throw new UnixIOException(Stdlib.GetLastError());
85 =>
throw new NotSupportedException();
88 public async ValueTask
CreateDump(global::System.Diagnostics.Process process,
string outputFile,
bool minidump, CancellationToken cancellationToken)
90 ArgumentNullException.ThrowIfNull(process);
91 ArgumentNullException.ThrowIfNull(outputFile);
93 string? gcorePath =
null;
101 if (gcorePath ==
null)
107 if (process.HasExited)
112 catch (InvalidOperationException ex)
121 Environment.CurrentDirectory,
122 $
"{(!minidump ? "-a
" : String.Empty)}-o {outputFile} {process.Id}",
124 readStandardHandles:
true,
125 noShellExecute:
true))
127 using (cancellationToken.Register(() => gcoreProc.Terminate()))
128 exitCode = (await gcoreProc.Lifetime).Value;
130 output = await gcoreProc.GetCombinedOutput(cancellationToken);
131 logger.LogDebug(
"gcore output:{newline}{output}", Environment.NewLine, output);
138 $
"Exit Code: {exitCode}{Environment.NewLine}Output:{Environment.NewLine}{output}"));
141 var generatedGCoreFile = $
"{outputFile}.{pid}";
146 public async ValueTask<int>
HandleProcessStart(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
148 ArgumentNullException.ThrowIfNull(process);
149 var pid = process.Id;
155 catch (
Exception ex) when (ex is not OperationCanceledException)
157 logger.LogWarning(ex,
"Failed to adjust OOM killer score for pid {pid}!", pid);
164 public async Task
StartAsync(CancellationToken cancellationToken)
167 string originalString;
172 "/proc/self/oom_score_adj",
true,
true);
173 using var reader =
new StreamReader(fileStream, Encoding.UTF8, leaveOpen:
true);
174 originalString = await reader.ReadToEndAsync(cancellationToken);
177 var trimmedString = originalString.Trim();
179 logger.LogTrace(
"Original oom_score_adj is \"{original}\"", trimmedString);
181 var originalOomAdjust = Int16.Parse(trimmedString, CultureInfo.InvariantCulture);
186 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);
188 logger.LogWarning(
"oom_score_adj is at it's limit of 1000. TGS cannot guarantee the kill order of its parent/child processes!");
195 catch (
Exception ex) when (ex is not OperationCanceledException)
197 logger.LogWarning(ex,
"Could not increase oom_score_adj!");
202 public Task
StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
215 var pidStr = pid.HasValue
216 ? pid.Value.ToString(CultureInfo.InvariantCulture)
219 "Setting oom_score_adj of {pid} to {adjustment}...", pidStr, adjustedValue);
221 $
"/proc/{pidStr}/oom_score_adj",
222 Encoding.UTF8.GetBytes(adjustedValue.ToString(CultureInfo.InvariantCulture)),
232 var enviromentPath = Environment.GetEnvironmentVariable(
"PATH");
233 IEnumerable<string> enumerator;
234 if (enviromentPath ==
null)
235 enumerator = Enumerable.Empty<
string>();
238 var paths = enviromentPath.Split(
';');
240 .Select(x => x.Split(
':'))
244 var exeName =
"gcore";
246 enumerator = enumerator
247 .Concat(
new List<string>(2)
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.
IEnumerable< string > GetPotentialGCorePaths()
Gets potential paths to the gcore executable.
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.
Stream CreateAsyncReadStream(string path, bool sequential, bool shareWrite)
Creates an asynchronous FileStream for sequential reading.
string ConcatPath(params string[] paths)
Combines an array of strings into a path.
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.