tgstation-server  4.3.2
The /tg/station 13 server suite
PosixProcessFeatures.cs
Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Mono.Unix;
3 using Mono.Unix.Native;
4 using System;
5 using System.Globalization;
6 using System.Linq;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Host.IO;
11 
12 namespace Tgstation.Server.Host.System
13 {
16  {
21 
25  readonly ILogger<PosixProcessFeatures> logger;
26 
32  public PosixProcessFeatures(IIOManager ioManager, ILogger<PosixProcessFeatures> logger)
33  {
34  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
35  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
36  }
37 
39  public void ResumeProcess(global::System.Diagnostics.Process process)
40  {
41  try
42  {
43  var result = Syscall.kill(process.Id, Signum.SIGCONT);
44  if (result != 0)
45  throw new UnixIOException(result);
46  logger.LogTrace("Resumed PID {0}", process.Id);
47  }
48  catch (Exception e)
49  {
50  logger.LogError(e, "Failed to resume PID {0}!", process.Id);
51  throw;
52  }
53  }
54 
56  public void SuspendProcess(global::System.Diagnostics.Process process)
57  {
58  try
59  {
60  var result = Syscall.kill(process.Id, Signum.SIGSTOP);
61  if (result != 0)
62  throw new UnixIOException(result);
63  logger.LogTrace("Resumed PID {0}", process.Id);
64  }
65  catch (Exception e)
66  {
67  logger.LogError(e, "Failed to suspend PID {0}!", process.Id);
68  throw;
69  }
70  }
71 
73  public async Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
74  {
75  if (process == null)
76  throw new ArgumentNullException(nameof(process));
77 
78  // Need to read /proc/[pid]/status
79  // http://man7.org/linux/man-pages/man5/proc.5.html
80  // https://unix.stackexchange.com/questions/102676/why-is-uid-information-not-in-proc-x-stat
81  var pid = process.Id;
82  var statusFile = ioManager.ConcatPath("/proc", pid.ToString(CultureInfo.InvariantCulture), "status");
83  var statusBytes = await ioManager.ReadAllBytes(statusFile, cancellationToken).ConfigureAwait(false);
84  var statusText = Encoding.UTF8.GetString(statusBytes);
85  var splits = statusText.Split('\n', StringSplitOptions.RemoveEmptyEntries);
86  var entry = splits.FirstOrDefault(x => x.Trim().StartsWith("Uid:", StringComparison.Ordinal));
87  if (entry == default)
88  return "UNKNOWN";
89 
90  return entry
91  .Substring(4)
92  .Split(' ', StringSplitOptions.RemoveEmptyEntries)
93  .FirstOrDefault(x => !String.IsNullOrWhiteSpace(x))
94  ?? "UNPARSABLE";
95  }
96  }
97 }
readonly IIOManager ioManager
The IIOManager for the PosixProcessFeatures.
readonly ILogger< PosixProcessFeatures > logger
The ILogger<TCategoryName> for the PosixProcessFeatures.
void SuspendProcess(global::System.Diagnostics.Process process)
Suspend a given Process.
PosixProcessFeatures(IIOManager ioManager, ILogger< PosixProcessFeatures > logger)
Initializes a new instance of the PosixProcessFeatures .
async Task< string > GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
Get the name of the user executing a given process .
Abstraction for suspending and resuming processes.
Interface for using filesystems
Definition: IIOManager.cs:11
void ResumeProcess(global::System.Diagnostics.Process process)
Resume a given suspended Process.