mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 16:39:21 +01:00
Add TGS3 style process suspend/resume while swapping
This commit is contained in:
@@ -130,11 +130,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
logger.LogTrace("Disposing...");
|
||||
disposed = true;
|
||||
repository.Dispose();
|
||||
onDispose();
|
||||
}
|
||||
|
||||
logger.LogTrace("Disposing...");
|
||||
repository.Dispose();
|
||||
onDispose();
|
||||
}
|
||||
|
||||
void GetRepositoryOwnerName(string remote, out string owner, out string name)
|
||||
|
||||
@@ -549,6 +549,12 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <inheritdoc />
|
||||
public void SetHighPriority() => process.SetHighPriority();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Suspend() => process.Suspend();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Resume() => process.Resume();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReplaceDmbProvider(IDmbProvider dmbProvider)
|
||||
{
|
||||
|
||||
@@ -120,7 +120,6 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
if (pendingSwappable != null)
|
||||
{
|
||||
Logger.LogTrace("Replacing activeSwappable with pendingSwappable");
|
||||
|
||||
Server.ReplaceDmbProvider(pendingSwappable);
|
||||
activeSwappable = pendingSwappable;
|
||||
pendingSwappable = null;
|
||||
@@ -139,7 +138,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
windowsProvider = new WindowsSwappableDmbProvider(compileJobProvider, ioManager, symlinkFactory);
|
||||
|
||||
Logger.LogDebug("Swapping to compile job {0}...", windowsProvider.CompileJob.Id);
|
||||
Server.Suspend();
|
||||
await windowsProvider.MakeActive(cancellationToken).ConfigureAwait(false);
|
||||
Server.Resume();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -24,6 +24,14 @@ namespace Tgstation.Server.Host
|
||||
AllowUnprivilegedCreate = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx
|
||||
/// </summary>
|
||||
public enum ThreadAccess : int
|
||||
{
|
||||
SuspendResume = 0x0002,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid
|
||||
/// </summary>
|
||||
@@ -70,5 +78,29 @@ namespace Tgstation.Server.Host
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags);
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335(v=vs.85).aspx
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern uint SuspendThread(IntPtr hThread);
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern uint ResumeThread(IntPtr hThread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,15 @@ namespace Tgstation.Server.Host.System
|
||||
/// Set's the owned <see cref="global::System.Diagnostics.Process.PriorityClass"/> to <see cref="global::System.Diagnostics.ProcessPriorityClass.AboveNormal"/>
|
||||
/// </summary>
|
||||
void SetHighPriority();
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the process.
|
||||
/// </summary>
|
||||
void Suspend();
|
||||
|
||||
/// <summary>
|
||||
/// Resumes the process.
|
||||
/// </summary>
|
||||
void Resume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using BetterWin32Errors;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -133,13 +135,65 @@ namespace Tgstation.Server.Host.System
|
||||
{
|
||||
try
|
||||
{
|
||||
handle.PriorityClass = global::System.Diagnostics.ProcessPriorityClass.AboveNormal;
|
||||
logger.LogTrace("Set to above normal priority", handle.Id);
|
||||
handle.PriorityClass = ProcessPriorityClass.AboveNormal;
|
||||
logger.LogTrace("Set PID {0} to above normal priority", Id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Unable to raise process priority! Exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Suspend()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (ProcessThread thread in handle.Threads)
|
||||
{
|
||||
var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
|
||||
if (pOpenThread == IntPtr.Zero)
|
||||
continue;
|
||||
|
||||
if (NativeMethods.SuspendThread(pOpenThread) == UInt32.MaxValue)
|
||||
throw new Win32Exception();
|
||||
|
||||
NativeMethods.CloseHandle(pOpenThread);
|
||||
}
|
||||
|
||||
logger.LogTrace("Suspended PID {0}", Id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Failed to suspend PID {0}!", Id);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Resume()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (ProcessThread thread in handle.Threads)
|
||||
{
|
||||
var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
|
||||
if (pOpenThread == IntPtr.Zero)
|
||||
continue;
|
||||
|
||||
if (NativeMethods.ResumeThread(pOpenThread) == UInt32.MaxValue)
|
||||
throw new Win32Exception();
|
||||
|
||||
NativeMethods.CloseHandle(pOpenThread);
|
||||
}
|
||||
|
||||
logger.LogTrace("Resumed PID {0}", Id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Failed to resume PID {0}!", Id);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user