From de83539befedf482caa781cfaa69672c20ce7440 Mon Sep 17 00:00:00 2001 From: madargs Date: Mon, 13 Feb 2017 15:24:23 +0000 Subject: [PATCH] Fixes #95 - Service not sending SIGINT properly to java (#186) * Fixes #95 - Service not sending SIGINT properly to java Detach from console process after sending SIGINT to java. Note: we still need to be set to true, so the parent (java) process is shut down first. Moved exception handling to GetChildPids. StopProcessAndChildren now gets a fresh list of childPids after stopping a parent process, as that may have caused some child processes to terminate. * Fixes #181 - V2 : WinSW.NET2.exe not working Latest version of ILMerge targets .NET4 by default when merging assemblies; specify target platform version for the .NET2 executable. * Fixes #95 - Service not sending SIGINT properly to java Error-checking for console detach, spaces indentation. #181 fix moved to separate branch. Revert "Fixes #181 - V2 : WinSW.NET2.exe not working" This reverts commit a089755cb9c127c582ad704cea4edbb437c21ba6. --- src/Core/WinSWCore/Util/ProcessHelper.cs | 40 +++++++++++------------- src/Core/WinSWCore/Util/SigIntHelper.cs | 14 ++++++++- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/Core/WinSWCore/Util/ProcessHelper.cs b/src/Core/WinSWCore/Util/ProcessHelper.cs index 5554a20..e26cf55 100644 --- a/src/Core/WinSWCore/Util/ProcessHelper.cs +++ b/src/Core/WinSWCore/Util/ProcessHelper.cs @@ -22,14 +22,22 @@ namespace winsw.Util /// List of child process PIDs public static List GetChildPids(int pid) { - var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid); var childPids = new List(); - foreach (var mo in searcher.Get()) - { - var childProcessId = mo["ProcessID"]; - Logger.Info("Found child process: " + childProcessId + " Name: " + mo["Name"]); - childPids.Add(Convert.ToInt32(childProcessId)); + + try { + var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid); + foreach (var mo in searcher.Get()) + { + var childProcessId = mo["ProcessID"]; + Logger.Info("Found child process: " + childProcessId + " Name: " + mo["Name"]); + childPids.Add(Convert.ToInt32(childProcessId)); + } } + catch (Exception ex) + { + Logger.Warn("Failed to locate children of the process with PID=" + pid + ". Child processes won't be terminated", ex); + } + return childPids; } @@ -90,19 +98,9 @@ namespace winsw.Util /// If enabled, the perent process will be terminated before its children on all levels public static void StopProcessAndChildren(int pid, TimeSpan stopTimeout, bool stopParentProcessFirst) { - List childPids = null; - try - { - childPids = GetChildPids(pid); - } - catch (Exception ex) - { - Logger.Warn("Failed to locate children of the process with PID=" + pid + ". Child processes won't be terminated", ex); - } - - if (!stopParentProcessFirst && childPids != null) - { - foreach (var childPid in childPids) + if (!stopParentProcessFirst) + { + foreach (var childPid in GetChildPids(pid)) { StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst); } @@ -110,9 +108,9 @@ namespace winsw.Util StopProcess(pid, stopTimeout); - if (stopParentProcessFirst && childPids != null) + if (stopParentProcessFirst) { - foreach (var childPid in childPids) + foreach (var childPid in GetChildPids(pid)) { StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst); } diff --git a/src/Core/WinSWCore/Util/SigIntHelper.cs b/src/Core/WinSWCore/Util/SigIntHelper.cs index 87e19f6..f7c5e0b 100644 --- a/src/Core/WinSWCore/Util/SigIntHelper.cs +++ b/src/Core/WinSWCore/Util/SigIntHelper.cs @@ -1,11 +1,15 @@ -using System; +using log4net; +using System; using System.Diagnostics; using System.Runtime.InteropServices; +using winsw.Native; namespace winsw.Util { public static class SigIntHelper { + private static readonly ILog Logger = LogManager.GetLogger(typeof(SigIntHelper)); + private const string KERNEL32 = "kernel32.dll"; [DllImport(KERNEL32, SetLastError = true)] @@ -49,6 +53,14 @@ namespace winsw.Util process.WaitForExit((int)shutdownTimeout.TotalMilliseconds); + // Detach from console. Causes child console process to be automatically closed. + bool success = FreeConsole(); + if (!success) + { + long errorCode = Kernel32.GetLastError(); + Logger.Warn("Failed to detach from console. Error code: " + errorCode); + } + return process.HasExited; }