mirror of https://github.com/winsw/winsw
Improve signal-related logging
parent
0bdd21b6c0
commit
f9e0126cf8
|
@ -2,6 +2,9 @@
|
|||
{
|
||||
internal static class Errors
|
||||
{
|
||||
internal const int ERROR_ACCESS_DENIED = 5;
|
||||
internal const int ERROR_INVALID_HANDLE = 6;
|
||||
internal const int ERROR_INVALID_PARAMETER = 7;
|
||||
internal const int ERROR_CANCELLED = 1223;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,17 +64,18 @@ namespace winsw.Util
|
|||
return;
|
||||
}
|
||||
|
||||
Logger.Info("Send SIGINT " + pid);
|
||||
bool successful = SigIntHelper.SendSIGINTToProcess(proc, stopTimeout);
|
||||
if (successful)
|
||||
{
|
||||
Logger.Info("SIGINT to " + pid + " successful");
|
||||
}
|
||||
else
|
||||
// (bool sent, bool exited)
|
||||
KeyValuePair<bool, bool> result = SignalHelper.SendCtrlCToProcess(proc, stopTimeout);
|
||||
bool exited = result.Value;
|
||||
if (!exited)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Warn("SIGINT to " + pid + " failed - Killing as fallback");
|
||||
bool sent = result.Key;
|
||||
if (sent)
|
||||
{
|
||||
Logger.Warn("Process " + pid + " did not respond to Ctrl+C signal - Killing as fallback");
|
||||
}
|
||||
proc.Kill();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using log4net;
|
||||
using winsw.Native;
|
||||
|
||||
namespace winsw.Util
|
||||
{
|
||||
public static class SigIntHelper
|
||||
{
|
||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(SigIntHelper));
|
||||
|
||||
/// <summary>
|
||||
/// Uses the native funciton "AttachConsole" to attach the thread to the executing process to try to trigger a CTRL_C event (SIGINT). If the application
|
||||
/// doesn't honor the event and shut down gracefully, the. wait period will time out after 15 seconds.
|
||||
/// </summary>
|
||||
/// <param name="process">The process to attach to and send the SIGINT</param>
|
||||
/// <returns>True if the process shut down successfully to the SIGINT, false if it did not.</returns>
|
||||
public static bool SendSIGINTToProcess(Process process, TimeSpan shutdownTimeout)
|
||||
{
|
||||
if (!ConsoleApis.AttachConsole(process.Id))
|
||||
{
|
||||
Logger.Warn("Failed to attach to console. Error code: " + Marshal.GetLastWin32Error());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable Ctrl-C handling for our program
|
||||
_ = ConsoleApis.SetConsoleCtrlHandler(null, true);
|
||||
_ = ConsoleApis.GenerateConsoleCtrlEvent(ConsoleApis.CtrlEvents.CTRL_C_EVENT, 0);
|
||||
|
||||
process.WaitForExit((int)shutdownTimeout.TotalMilliseconds);
|
||||
|
||||
// Detach from console. Causes child console process to be automatically closed.
|
||||
bool succeeded = ConsoleApis.FreeConsole();
|
||||
Debug.Assert(succeeded);
|
||||
|
||||
return process.HasExited;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using log4net;
|
||||
using winsw.Native;
|
||||
|
||||
namespace winsw.Util
|
||||
{
|
||||
internal static class SignalHelper
|
||||
{
|
||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(SignalHelper));
|
||||
|
||||
// (bool sent, bool exited)
|
||||
internal static KeyValuePair<bool, bool> SendCtrlCToProcess(Process process, TimeSpan shutdownTimeout)
|
||||
{
|
||||
if (!ConsoleApis.AttachConsole(process.Id))
|
||||
{
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
Logger.Warn("Failed to attach to console. " + error switch
|
||||
{
|
||||
Errors.ERROR_ACCESS_DENIED => "WinSW is already attached to a console.", // TODO: test mode
|
||||
Errors.ERROR_INVALID_HANDLE => "The process does not have a console.",
|
||||
Errors.ERROR_INVALID_PARAMETER => "The process has exited.",
|
||||
_ => new Win32Exception(error).Message // unreachable
|
||||
});
|
||||
|
||||
return new KeyValuePair<bool, bool>(false, error == Errors.ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
_ = ConsoleApis.SetConsoleCtrlHandler(null, true);
|
||||
_ = ConsoleApis.GenerateConsoleCtrlEvent(ConsoleApis.CtrlEvents.CTRL_C_EVENT, 0);
|
||||
_ = ConsoleApis.SetConsoleCtrlHandler(null, false);
|
||||
bool succeeded = ConsoleApis.FreeConsole();
|
||||
Debug.Assert(succeeded);
|
||||
|
||||
return new KeyValuePair<bool, bool>(true, process.WaitForExit((int)shutdownTimeout.TotalMilliseconds));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue