Client LuaCsForBarotrauma
BarotraumaClient/ClientSource/Networking/ChildServerRelay.cs
1 using System.Diagnostics;
2 using System.IO.Pipes;
3 using System.Linq;
4 using System.Threading;
5 
6 namespace Barotrauma.Networking
7 {
8  static partial class ChildServerRelay
9  {
10  public static Process Process;
11  public static bool IsProcessAlive => Process is { HasExited: false };
12 
13  private static bool localHandlesDisposed;
14  private static AnonymousPipeServerStream writePipe;
15  private static AnonymousPipeServerStream readPipe;
16 
17  public static void Start(ProcessStartInfo processInfo)
18  {
19  CrashString = null;
20  CrashReportFilePath = null;
21 
22  writePipe = new AnonymousPipeServerStream(PipeDirection.Out, System.IO.HandleInheritability.Inheritable);
23  readPipe = new AnonymousPipeServerStream(PipeDirection.In, System.IO.HandleInheritability.Inheritable);
24 
25  writeStream = writePipe; readStream = readPipe;
26 
27  PrivateStart();
28 
29  processInfo.ArgumentList.Add("-pipes");
30  processInfo.ArgumentList.Add(writePipe.GetClientHandleAsString());
31  processInfo.ArgumentList.Add(readPipe.GetClientHandleAsString());
32  try
33  {
34  Process = Process.Start(processInfo);
35  }
36  catch
37  {
38  DebugConsole.ThrowError($"Failed to start ChildServerRelay Process. File: {processInfo.FileName}, arguments: {processInfo.Arguments}");
39  ForceShutDown();
40  throw;
41  }
42 
43  localHandlesDisposed = false;
44  }
45 
46  public static void DisposeLocalHandles()
47  {
48  if (localHandlesDisposed) { return; }
49  writePipe.DisposeLocalCopyOfClientHandle(); readPipe.DisposeLocalCopyOfClientHandle();
50  localHandlesDisposed = true;
51  }
52 
53  public static void AttemptGracefulShutDown(int maxAttempts = 20)
54  {
55  status = StatusEnum.RequestedShutDown;
56  writeManualResetEvent?.Set();
57  int checks = 0;
58  while (Process is { HasExited: false })
59  {
60  if (checks >= maxAttempts)
61  {
62  DebugConsole.AddWarning("Server could not be shut down gracefully");
63  break;
64  }
65  Thread.Sleep(100);
66  checks++;
67  }
68  ForceShutDown();
69  }
70 
71  public static void ForceShutDown()
72  {
73  Process?.Kill(); Process = null;
74  PrivateShutDown();
75  }
76 
77  public static string CrashString { get; private set; }
78  public static string CrashReportFilePath { get; private set; }
79 
80  public static LocalizedString CrashMessage
81  => string.IsNullOrEmpty(CrashReportFilePath)
82  ? TextManager.Get("ServerProcessClosed")
83  : TextManager.GetWithVariable("ServerProcessCrashed", "[reportfilepath]", CrashReportFilePath);
84 
85  static partial void HandleCrashString(string str)
86  {
87  DebugConsole.ThrowError($"The server has crashed: {str}");
88  CrashReportFilePath = str.Split("||").FirstOrDefault() ?? "servercrashreport.log";
89  CrashString = str;
90  }
91  }
92 }