From 4ccd3e09b846725e6dd6823c4f161e770a06115e Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 29 Jun 2017 14:35:47 -0400 Subject: [PATCH] DreamDaemon is now suspended while symswap happens (#54) * DreamDaemon is now suspended while symswap happens * Fix --- TGServerService/Compiler.cs | 25 ++++++------ TGServerService/ProcessExtension.cs | 55 ++++++++++++++++++++++++++ TGServerService/TGServerService.csproj | 1 + 3 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 TGServerService/ProcessExtension.cs diff --git a/TGServerService/Compiler.cs b/TGServerService/Compiler.cs index 57760fd066..63fbe5b8d8 100644 --- a/TGServerService/Compiler.cs +++ b/TGServerService/Compiler.cs @@ -433,20 +433,21 @@ namespace TGServerService try { //gotta go fast - if (currentStatus == TGDreamDaemonStatus.Online) + var online = currentStatus == TGDreamDaemonStatus.Online; + if(online) + Proc.Suspend(); + try { - Thread.CurrentThread.Priority = ThreadPriority.Highest; - Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; - try - { - Proc.PriorityClass = ProcessPriorityClass.Idle; - } - catch { } + if (Directory.Exists(GameDirLive)) + //these two lines should be atomic but this is the best we can do + Directory.Delete(GameDirLive); + CreateSymlink(GameDirLive, resurrectee); + } + finally + { + if(online && !Proc.HasExited) + Proc.Resume(); } - if (Directory.Exists(GameDirLive)) - //these two lines should be atomic but this is the best we can do - Directory.Delete(GameDirLive); - CreateSymlink(GameDirLive, resurrectee); } finally { diff --git a/TGServerService/ProcessExtension.cs b/TGServerService/ProcessExtension.cs new file mode 100644 index 0000000000..3fc590b89b --- /dev/null +++ b/TGServerService/ProcessExtension.cs @@ -0,0 +1,55 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace TGServerService +{ + //lightly massaged code from https://stackoverflow.com/a/13109774 + public static class ProcessExtension + { + enum ThreadAccess : int + { + TERMINATE = (0x0001), + SUSPEND_RESUME = (0x0002), + GET_CONTEXT = (0x0008), + SET_CONTEXT = (0x0010), + SET_INFORMATION = (0x0020), + QUERY_INFORMATION = (0x0040), + SET_THREAD_TOKEN = (0x0080), + IMPERSONATE = (0x0100), + DIRECT_IMPERSONATION = (0x0200) + } + + [DllImport("kernel32.dll")] + static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + [DllImport("kernel32.dll")] + static extern bool CloseHandle(IntPtr hObject); + [DllImport("kernel32.dll")] + static extern uint SuspendThread(IntPtr hThread); + [DllImport("kernel32.dll")] + static extern int ResumeThread(IntPtr hThread); + + public static void Suspend(this Process process) + { + foreach (ProcessThread thread in process.Threads) + { + var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + continue; + SuspendThread(pOpenThread); + CloseHandle(pOpenThread); + } + } + public static void Resume(this Process process) + { + foreach (ProcessThread thread in process.Threads) + { + var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + continue; + ResumeThread(pOpenThread); + CloseHandle(pOpenThread); + } + } + } +} diff --git a/TGServerService/TGServerService.csproj b/TGServerService/TGServerService.csproj index b5a28de59e..55d8dbed62 100644 --- a/TGServerService/TGServerService.csproj +++ b/TGServerService/TGServerService.csproj @@ -92,6 +92,7 @@ + True True