From 05092376f30959c9fe6068542916a3684171db07 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Thu, 8 Jun 2017 22:54:44 +0200 Subject: [PATCH 1/2] Issue #218 - ProcessHelper#StartProcessAndCallbackForExit() should redirect STDOUT/STDERR when LogHandler is defined It restores logging of executables, which has been broken in https://github.com/kohsuke/winsw/pull/220. Not a regression, because the change has not been released yet --- src/Core/ServiceWrapper/Main.cs | 19 ++++++++++--------- src/Core/WinSWCore/Util/ProcessHelper.cs | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Core/ServiceWrapper/Main.cs b/src/Core/ServiceWrapper/Main.cs index 2f3d3b4..1d25716 100644 --- a/src/Core/ServiceWrapper/Main.cs +++ b/src/Core/ServiceWrapper/Main.cs @@ -136,7 +136,8 @@ namespace winsw /// /// Handle the creation of the logfiles based on the optional logmode setting. /// - private void HandleLogfiles() + /// Log Handler, which should be used for the spawned process + private LogHandler CreateExecutableLogHandler() { string logDirectory = _descriptor.LogDirectory; @@ -147,7 +148,7 @@ namespace winsw LogHandler logAppender = _descriptor.LogHandler; logAppender.EventLogger = this; - logAppender.log(_process.StandardOutput.BaseStream, _process.StandardError.BaseStream); + return logAppender; } public void LogEvent(String message) @@ -247,12 +248,10 @@ namespace winsw LogEvent("Starting " + _descriptor.Executable + ' ' + startarguments); Log.Info("Starting " + _descriptor.Executable + ' ' + startarguments); - StartProcess(_process, startarguments, _descriptor.Executable); + LogHandler executableLogHandler = CreateExecutableLogHandler(); + StartProcess(_process, startarguments, _descriptor.Executable, executableLogHandler); ExtensionManager.FireOnProcessStarted(_process); - // send stdout and stderr to its respective output file. - HandleLogfiles(); - _process.StandardInput.Close(); // nothing for you to read! } @@ -322,7 +321,8 @@ namespace winsw executable = _descriptor.Executable; } - StartProcess(stopProcess, stoparguments, executable); + // TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated + StartProcess(stopProcess, stoparguments, executable, null); Log.Debug("WaitForProcessToExit " + _process.Id + "+" + stopProcess.Id); WaitForProcessToExit(_process); @@ -407,7 +407,7 @@ namespace winsw Advapi32.SetServiceStatus(handle, ref _wrapperServiceStatus); } - private void StartProcess(Process processToStart, string arguments, String executable) + private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler) { // Define handler of the completed process @@ -454,7 +454,8 @@ namespace winsw envVars: _envs, workingDirectory: _descriptor.WorkingDirectory, priority: _descriptor.Priority, - callback: processCompletionCallback); + callback: processCompletionCallback, + logHandler: logHandler); } public static int Main(string[] args) diff --git a/src/Core/WinSWCore/Util/ProcessHelper.cs b/src/Core/WinSWCore/Util/ProcessHelper.cs index a51b5dc..8696dbe 100644 --- a/src/Core/WinSWCore/Util/ProcessHelper.cs +++ b/src/Core/WinSWCore/Util/ProcessHelper.cs @@ -129,8 +129,9 @@ namespace winsw.Util /// Working directory /// Priority /// Completion callback. If null, the completion won't be monitored + /// Log handler. If enabled, logs will be redirected to the process and then reported public static void StartProcessAndCallbackForExit(Process processToStart, String executable = null, string arguments = null, Dictionary envVars = null, - string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = null) + string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = null, LogHandler logHandler = null) { var ps = processToStart.StartInfo; ps.FileName = executable ?? ps.FileName; @@ -138,9 +139,9 @@ namespace winsw.Util ps.WorkingDirectory = workingDirectory ?? ps.WorkingDirectory; ps.CreateNoWindow = false; ps.UseShellExecute = false; - ps.RedirectStandardInput = false; - ps.RedirectStandardOutput = false; - ps.RedirectStandardError = false; + ps.RedirectStandardInput = false; + ps.RedirectStandardOutput = logHandler != null; + ps.RedirectStandardError = logHandler != null; if (envVars != null) { @@ -160,6 +161,13 @@ namespace winsw.Util processToStart.PriorityClass = priority.Value; } + // Redirect logs if required + if (logHandler != null) + { + Logger.Debug("Forwarding logs of the process " + processToStart + " to " + logHandler); + logHandler.log(processToStart.StandardOutput.BaseStream, processToStart.StandardError.BaseStream); + } + // monitor the completion of the process if (callback != null) { From 69857d5d8c4f7b94f4053b3aeef76b809908ca4e Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Thu, 8 Jun 2017 23:44:24 +0200 Subject: [PATCH 2/2] Issue #218 - Also support managing Stdin, which is required in the main executable logic --- src/Core/ServiceWrapper/Main.cs | 9 +++++---- src/Core/WinSWCore/Util/ProcessHelper.cs | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Core/ServiceWrapper/Main.cs b/src/Core/ServiceWrapper/Main.cs index 1d25716..8dc99d4 100644 --- a/src/Core/ServiceWrapper/Main.cs +++ b/src/Core/ServiceWrapper/Main.cs @@ -249,7 +249,7 @@ namespace winsw Log.Info("Starting " + _descriptor.Executable + ' ' + startarguments); LogHandler executableLogHandler = CreateExecutableLogHandler(); - StartProcess(_process, startarguments, _descriptor.Executable, executableLogHandler); + StartProcess(_process, startarguments, _descriptor.Executable, executableLogHandler, true); ExtensionManager.FireOnProcessStarted(_process); _process.StandardInput.Close(); // nothing for you to read! @@ -322,7 +322,7 @@ namespace winsw } // TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated - StartProcess(stopProcess, stoparguments, executable, null); + StartProcess(stopProcess, stoparguments, executable, null, false); Log.Debug("WaitForProcessToExit " + _process.Id + "+" + stopProcess.Id); WaitForProcessToExit(_process); @@ -407,7 +407,7 @@ namespace winsw Advapi32.SetServiceStatus(handle, ref _wrapperServiceStatus); } - private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler) + private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler, bool redirectStdin) { // Define handler of the completed process @@ -455,7 +455,8 @@ namespace winsw workingDirectory: _descriptor.WorkingDirectory, priority: _descriptor.Priority, callback: processCompletionCallback, - logHandler: logHandler); + logHandler: logHandler, + redirectStdin: redirectStdin); } public static int Main(string[] args) diff --git a/src/Core/WinSWCore/Util/ProcessHelper.cs b/src/Core/WinSWCore/Util/ProcessHelper.cs index 8696dbe..5412ace 100644 --- a/src/Core/WinSWCore/Util/ProcessHelper.cs +++ b/src/Core/WinSWCore/Util/ProcessHelper.cs @@ -130,8 +130,9 @@ namespace winsw.Util /// Priority /// Completion callback. If null, the completion won't be monitored /// Log handler. If enabled, logs will be redirected to the process and then reported + /// Redirect standard input public static void StartProcessAndCallbackForExit(Process processToStart, String executable = null, string arguments = null, Dictionary envVars = null, - string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = null, LogHandler logHandler = null) + string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = null, bool redirectStdin = true, LogHandler logHandler = null) { var ps = processToStart.StartInfo; ps.FileName = executable ?? ps.FileName; @@ -139,7 +140,7 @@ namespace winsw.Util ps.WorkingDirectory = workingDirectory ?? ps.WorkingDirectory; ps.CreateNoWindow = false; ps.UseShellExecute = false; - ps.RedirectStandardInput = false; + ps.RedirectStandardInput = redirectStdin; ps.RedirectStandardOutput = logHandler != null; ps.RedirectStandardError = logHandler != null;