tgstation-server
The /tg/station 13 server suite
Process.cs
Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Text;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Core
7 {
9  sealed class Process : IProcess
10  {
12  public int Id { get; }
13 
15  public Task Startup { get; }
16 
18  public Task<int> Lifetime { get; }
19 
20  readonly System.Diagnostics.Process handle;
21 
22  readonly StringBuilder outputStringBuilder;
23  readonly StringBuilder errorStringBuilder;
24  readonly StringBuilder combinedStringBuilder;
25 
29  readonly ILogger<Process> logger;
30 
31  public Process(System.Diagnostics.Process handle, Task<int> lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger<Process> logger, bool preExisting)
32  {
33  this.handle = handle ?? throw new ArgumentNullException(nameof(handle));
34  Lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
35 
36  this.outputStringBuilder = outputStringBuilder;
37  this.errorStringBuilder = errorStringBuilder;
38  this.combinedStringBuilder = combinedStringBuilder;
39 
40  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
41 
42  Id = handle.Id;
43 
44  if (preExisting)
45  {
46  Startup = Task.CompletedTask;
47  return;
48  }
49 
50  Startup = Task.Factory.StartNew(() =>
51  {
52  try
53  {
54  handle.WaitForInputIdle();
55  }
56  catch (InvalidOperationException) { }
57  }, default, TaskCreationOptions.LongRunning, TaskScheduler.Current);
58 
59  logger.LogTrace("Created process ID: {0}", Id);
60  }
61 
63  public void Dispose() => handle.Dispose();
64 
66  public string GetCombinedOutput()
67  {
68  if (combinedStringBuilder == null)
69  throw new InvalidOperationException("Output/Error reading was not enabled!");
70  return combinedStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
71  }
72 
74  public string GetErrorOutput()
75  {
76  if (errorStringBuilder == null)
77  throw new InvalidOperationException("Error reading was not enabled!");
78  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
79  }
80 
82  public string GetStandardOutput()
83  {
84  if (outputStringBuilder == null)
85  throw new InvalidOperationException("Output reading was not enabled!");
86  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
87  }
88 
90  public void Terminate()
91  {
92  if (handle.HasExited)
93  return;
94  try
95  {
96  logger.LogTrace("Terminating process...");
97  handle.Kill();
98  handle.WaitForExit();
99  }
100  catch (Exception e)
101  {
102  logger.LogDebug("Process termination exception: {0}", e);
103  }
104  }
105 
106  public void SetHighPriority()
107  {
108  try
109  {
110  handle.PriorityClass = System.Diagnostics.ProcessPriorityClass.AboveNormal;
111  logger.LogTrace("Set to above normal priority", handle.Id);
112  }
113  catch (Exception e)
114  {
115  logger.LogWarning("Unable to raise process priority! Exception: {0}", e);
116  }
117  }
118  }
119 }
readonly StringBuilder errorStringBuilder
Definition: Process.cs:23
string GetErrorOutput()
Get the stderr output of the IProcess
Definition: Process.cs:74
Process(System.Diagnostics.Process handle, Task< int > lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger< Process > logger, bool preExisting)
Definition: Process.cs:31
readonly StringBuilder combinedStringBuilder
Definition: Process.cs:24
string GetStandardOutput()
Get the stdout output of the IProcess
Definition: Process.cs:82
string GetCombinedOutput()
Get the stderr and stdout output of the IProcess
Definition: Process.cs:66
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
void SetHighPriority()
Set&#39;s the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal
Definition: Process.cs:106
readonly ILogger< Process > logger
The ILogger for the Process
Definition: Process.cs:29
readonly System.Diagnostics.Process handle
Definition: Process.cs:20
readonly StringBuilder outputStringBuilder
Definition: Process.cs:22
void Terminate()
Terminates the process
Definition: Process.cs:90