Browse Source

Merge pull request #224 from oleg-nenashev/bug/Issue218_fix2

Issue #218 - ProcessHelper#StartProcessAndCallbackForExit() should redirect STDOUT/STDERR when LogHandler is defined
Oleg Nenashev 8 years ago
parent
commit
a2c2a9d405
2 changed files with 24 additions and 13 deletions
  1. 11 9
      src/Core/ServiceWrapper/Main.cs
  2. 13 4
      src/Core/WinSWCore/Util/ProcessHelper.cs

+ 11 - 9
src/Core/ServiceWrapper/Main.cs

@@ -136,7 +136,8 @@ namespace winsw
         /// <summary>
         /// Handle the creation of the logfiles based on the optional logmode setting.
         /// </summary>
-        private void HandleLogfiles()
+        /// <returns>Log Handler, which should be used for the spawned process</returns>
+        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, true);
             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, 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)
+        private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler, bool redirectStdin)
         {
             
             // Define handler of the completed process
@@ -454,7 +454,9 @@ namespace winsw
                 envVars: _envs,
                 workingDirectory: _descriptor.WorkingDirectory,
                 priority: _descriptor.Priority,
-                callback: processCompletionCallback);
+                callback: processCompletionCallback,
+                logHandler: logHandler,
+                redirectStdin: redirectStdin);
         }
 
         public static int Main(string[] args)

+ 13 - 4
src/Core/WinSWCore/Util/ProcessHelper.cs

@@ -129,8 +129,10 @@ namespace winsw.Util
         /// <param name="workingDirectory">Working directory</param>
         /// <param name="priority">Priority</param>
         /// <param name="callback">Completion callback. If null, the completion won't be monitored</param>
+        /// <param name="logHandler">Log handler. If enabled, logs will be redirected to the process and then reported</param>
+        /// <param name="redirectStdin">Redirect standard input</param>
         public static void StartProcessAndCallbackForExit(Process processToStart, String executable = null, string arguments = null, Dictionary<string, string> envVars = null,
-            string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = 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;
@@ -138,9 +140,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 = redirectStdin;
+            ps.RedirectStandardOutput = logHandler != null;
+            ps.RedirectStandardError = logHandler != null;
 
             if (envVars != null)
             {
@@ -160,6 +162,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)
             {