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));
73 var enviromentPath = Environment.GetEnvironmentVariable(
"PATH");
74 IEnumerable<string> enumerator;
75 if (enviromentPath ==
null)
76 enumerator = Enumerable.Empty<
string>();
79 var paths = enviromentPath.Split(
';');
81 .Select(x => x.Split(
':'))
85 var exeName =
"gcore";
87 enumerator = enumerator
88 .Concat(
new List<string>(2)
95 enumerator = enumerator.Select(x => Path.Combine(x, exeName));
103 var result = Syscall.kill(process.Id, Signum.SIGCONT);
105 throw new UnixIOException(Stdlib.GetLastError());
111 var result = Syscall.kill(process.Id, Signum.SIGSTOP);
113 throw new UnixIOException(Stdlib.GetLastError());
118 =>
throw new NotSupportedException();
121 public async ValueTask
CreateDump(global::System.Diagnostics.Process process,
string outputFile,
bool minidump, CancellationToken cancellationToken)
123 ArgumentNullException.ThrowIfNull(process);
124 ArgumentNullException.ThrowIfNull(outputFile);
126 string? gcorePath =
null;
134 if (gcorePath ==
null)
140 if (process.HasExited)
145 catch (InvalidOperationException ex)
154 Environment.CurrentDirectory,
155 $
"{(!minidump ? "-a
" : String.Empty)}-o {outputFile} {process.Id}",
157 readStandardHandles:
true,
158 noShellExecute:
true))
160 using (cancellationToken.Register(() => gcoreProc.Terminate()))
161 exitCode = (await gcoreProc.Lifetime).Value;
163 output = await gcoreProc.GetCombinedOutput(cancellationToken);
164 logger.LogDebug(
"gcore output:{newline}{output}", Environment.NewLine, output);
171 $
"Exit Code: {exitCode}{Environment.NewLine}Output:{Environment.NewLine}{output}"));
174 var generatedGCoreFile = $
"{outputFile}.{pid}";
179 public async ValueTask<int>
HandleProcessStart(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
181 ArgumentNullException.ThrowIfNull(process);
182 var pid = process.Id;
188 catch (
Exception ex) when (ex is not OperationCanceledException)
190 logger.LogWarning(ex,
"Failed to adjust OOM killer score for pid {pid}!", pid);
197 public async Task
StartAsync(CancellationToken cancellationToken)
200 string originalString;
205 "/proc/self/oom_score_adj");
206 using var reader =
new StreamReader(fileStream, Encoding.UTF8, leaveOpen:
true);
207 originalString = await reader.ReadToEndAsync(cancellationToken);
210 var trimmedString = originalString.Trim();
212 logger.LogTrace(
"Original oom_score_adj is \"{original}\"", trimmedString);
214 var originalOomAdjust = Int16.Parse(trimmedString, CultureInfo.InvariantCulture);
219 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);
221 logger.LogWarning(
"oom_score_adj is at it's limit of 1000. TGS cannot guarantee the kill order of its parent/child processes!");
228 catch (
Exception ex) when (ex is not OperationCanceledException)
230 logger.LogWarning(ex,
"Could not increase oom_score_adj!");
235 public Task
StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
248 var pidStr = pid.HasValue
249 ? pid.Value.ToString(CultureInfo.InvariantCulture)
252 "Setting oom_score_adj of {pid} to {adjustment}...", pidStr, adjustedValue);
254 $
"/proc/{pidStr}/oom_score_adj",
255 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 .
static IEnumerable< string > GetPotentialGCorePaths()
Gets potential paths to the gcore executable.
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.