RunawayProcessKillerExtension: Check if the environment variable refers service Id before terminating it

pull/133/head
Oleg Nenashev 2016-11-30 12:37:07 +01:00
parent 5e835479ae
commit 92367f44ef
2 changed files with 40 additions and 0 deletions

View File

@ -424,8 +424,13 @@ namespace winsw
ps.RedirectStandardError = true;
foreach (string key in _envs.Keys)
{
Environment.SetEnvironmentVariable(key, _envs[key]);
// ps.EnvironmentVariables[key] = envs[key]; // bugged (lower cases all variable names due to StringDictionary being used, see http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=326163)
}
// TODO: Make it generic via extension points. The issue mentioned above should be ideally worked around somehow
ps.EnvironmentVariables[WinSWSystem.ENVVAR_NAME_SERVICE_ID.ToLower()] = _descriptor.Id;
processToStart.Start();
WriteEvent("Started " + processToStart.Id);

View File

@ -5,6 +5,7 @@ using System.Diagnostics;
using winsw.Extensions;
using winsw.Util;
using log4net;
using System.Collections.Specialized;
namespace winsw.Plugins.RunawayProcessKiller
{
@ -28,6 +29,8 @@ namespace winsw.Plugins.RunawayProcessKiller
public override String DisplayName { get { return "Runaway Process Killer"; } }
private String ServiceId { get; set; }
private static readonly ILog Logger = LogManager.GetLogger(typeof(RunawayProcessKillerExtension));
public RunawayProcessKillerExtension()
@ -47,6 +50,7 @@ namespace winsw.Plugins.RunawayProcessKiller
Pidfile = XmlHelper.SingleElement(node, "pidfile", false);
StopTimeout = TimeSpan.FromMilliseconds(Int32.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)));
StopParentProcessFirst = Boolean.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false));
ServiceId = descriptor.Id;
}
/// <summary>
@ -96,7 +100,38 @@ namespace winsw.Plugins.RunawayProcessKiller
return;
}
// Ensure the process references the service
String affiliatedServiceId;
// TODO: This method is not ideal since it works only for vars explicitly mentioned in the start info
// No Windows 10- compatible solution for EnvVars retrieval, see https://blog.gapotchenko.com/eazfuscator.net/reading-environment-variables
StringDictionary previousProcessEnvVars = proc.StartInfo.EnvironmentVariables;
String expectedEnvVarName = WinSWSystem.ENVVAR_NAME_SERVICE_ID.ToLower();
if (previousProcessEnvVars.ContainsKey(expectedEnvVarName))
{
affiliatedServiceId = previousProcessEnvVars[expectedEnvVarName];
}
else
{
Logger.Warn("The process " + pid + " has no " + expectedEnvVarName + " environment variable defined. "
+ "The process has not been started by this service, hence it won't be terminated.");
if (Logger.IsDebugEnabled) {
foreach (string key in previousProcessEnvVars.Keys) {
Logger.Debug("Env var of " + pid + ": " + key + "=" + previousProcessEnvVars[key]);
}
}
return;
}
// Check the service ID value
if (!ServiceId.Equals(affiliatedServiceId))
{
Logger.Warn("The process " + pid + " has been started by Windows service with ID='" + affiliatedServiceId + "'. "
+ "It is another service (current service id is '" + ServiceId + "'), hence the process won't be terminated.");
return;
}
// Kill the runaway process
Logger.Warn("Stopping the runaway process (pid=" + pid + ") and its children.");
ProcessHelper.StopProcessAndChildren(pid, this.StopTimeout, this.StopParentProcessFirst);
}