From b4a37f07cc3fb48c2e091cee0a436a37944292c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanko=20Krsti=C4=87?= Date: Tue, 23 May 2017 10:16:05 +0200 Subject: [PATCH] GC shutdown --- NiceHashMiner/Forms/Form_Main.cs | 2 +- NiceHashMiner/Miners/Miner.cs | 5 +- NiceHashMiner/PInvoke/NiceHashProcess.cs | 73 ++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/NiceHashMiner/Forms/Form_Main.cs b/NiceHashMiner/Forms/Form_Main.cs index 3b7746b..8831b02 100644 --- a/NiceHashMiner/Forms/Form_Main.cs +++ b/NiceHashMiner/Forms/Form_Main.cs @@ -51,7 +51,7 @@ public partial class Form_Main : Form, Form_Loading.IAfterInitializationCaller, int flowLayoutPanelVisibleCount = 0; int flowLayoutPanelRatesIndex = 0; - const string _betaAlphaPostfixString = ""; + const string _betaAlphaPostfixString = " - Graceful Shutdown"; private bool _isDeviceDetectionInitialized = false; diff --git a/NiceHashMiner/Miners/Miner.cs b/NiceHashMiner/Miners/Miner.cs index 5d42949..ca24b07 100644 --- a/NiceHashMiner/Miners/Miner.cs +++ b/NiceHashMiner/Miners/Miner.cs @@ -260,12 +260,13 @@ protected void Stop_cpu_ccminer_sgminer_nheqminer(MinerStopType willswitch) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Shutting down miner"); } if (ProcessHandle != null) { - try { ProcessHandle.Kill(); } catch { } + //try { ProcessHandle.Kill(); } catch { } + try { ProcessHandle.SendCtrlC((uint)Process.GetCurrentProcess().Id); } catch { } ProcessHandle.Close(); ProcessHandle = null; // sgminer needs to be removed and kill by PID - if (IsKillAllUsedMinerProcs) KillAllUsedMinerProcesses(); + //if (IsKillAllUsedMinerProcs) KillAllUsedMinerProcesses(); } } diff --git a/NiceHashMiner/PInvoke/NiceHashProcess.cs b/NiceHashMiner/PInvoke/NiceHashProcess.cs index 4ca98d5..f78dea6 100644 --- a/NiceHashMiner/PInvoke/NiceHashProcess.cs +++ b/NiceHashMiner/PInvoke/NiceHashProcess.cs @@ -92,6 +92,38 @@ private static extern bool CreateProcess( static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, uint nSize); + // ctrl+c + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool AttachConsole(uint dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + static extern bool FreeConsole(); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); + + [DllImport("Kernel32", SetLastError = true)] + private static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add); + + [DllImportAttribute("kernel32.dll", EntryPoint = "AllocConsole")] + [return: MarshalAsAttribute(UnmanagedType.Bool)] + public static extern bool AllocConsole(); + + [DllImport("kernel32.dll")] + static extern uint GetLastError(); + + enum CtrlTypes { + CTRL_C_EVENT = 0, + CTRL_BREAK_EVENT, + CTRL_CLOSE_EVENT, + CTRL_LOGOFF_EVENT = 5, + CTRL_SHUTDOWN_EVENT + } + + // A delegate type to be used as the handler routine + // for SetConsoleCtrlHandler. + private delegate bool HandlerRoutine(CtrlTypes CtrlType); + public delegate void ExitEventDelegate(); public ProcessStartInfo StartInfo; @@ -199,6 +231,47 @@ public void Close() pHandle = IntPtr.Zero; } + bool signalCtrl(uint thisConsoleId, uint dwProcessId, CtrlTypes dwCtrlEvent) { + bool success = false; + //uint thisConsoleId = GetCurrentProcessId(); + // Leave current console if it exists + // (otherwise AttachConsole will return ERROR_ACCESS_DENIED) + bool consoleDetached = (FreeConsole() != false); + + if (AttachConsole(dwProcessId) != false) { + // Add a fake Ctrl-C handler for avoid instant kill is this console + // WARNING: do not revert it or current program will be also killed + SetConsoleCtrlHandler(null, true); + success = (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) != false); + FreeConsole(); + // wait for termination so we don't terminate NHM + WaitForSingleObject(pHandle, 10000); + } + + if (consoleDetached) { + // Create a new console if previous was deleted by OS + if (AttachConsole(thisConsoleId) == false) { + uint errorCode = GetLastError(); + if (errorCode == 31) { // 31=ERROR_GEN_FAILURE + AllocConsole(); + } + } + SetConsoleCtrlHandler(null, false); + } + return success; + } + + public void SendCtrlC(uint thisConsoleId) { + if (pHandle == IntPtr.Zero) return; + + if (tHandle != null) { + bRunning = false; + tHandle.Join(); + } + signalCtrl(thisConsoleId, (uint)this.Id, CtrlTypes.CTRL_C_EVENT); + pHandle = IntPtr.Zero; + } + private void cThread() { while (bRunning)