[xbuild] Fix a race condition in ToolTask.
authorAnkit Jain <radical@corewars.org>
Wed, 15 Sep 2010 13:39:34 +0000 (19:09 +0530)
committerAnkit Jain <radical@corewars.org>
Wed, 15 Sep 2010 16:51:03 +0000 (22:21 +0530)
 * class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs
 (ExecuteTool): When StartProcess returns, the process has already .Start()'ed
 If we subscribe to the output events after that, then for processes that
 finish executing before we can subscribe, we won't get the output/error
 events at all! So, pass the handlers to StartProcess itself, so that
 they get added before the process is started.

mcs/class/Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolTask.cs

index 91f95adfcc358da8e57d4c53352ffc663205feda..b2dbb38606ea4af8d4455fb0ce46d06edd1a4088 100644 (file)
@@ -112,11 +112,8 @@ namespace Microsoft.Build.Utilities
                        if (pathToTool == null)
                                throw new ArgumentNullException ("pathToTool");
 
-                       string output, error, responseFileName;
-                       StreamWriter outwr, errwr;
-
-                       outwr = errwr = null;
-                       responseFileName = output = error = null;
+                       string responseFileName;
+                       responseFileName = null;
                        toolOutput = new StringBuilder ();
 
                        try {
@@ -130,11 +127,6 @@ namespace Microsoft.Build.Utilities
                                LogToolCommand (String.Format ("Tool {0} execution started with arguments: {1} {2}",
                                                pathToTool, commandLineCommands, responseFileCommands));
 
-                               output = Path.GetTempFileName ();
-                               error = Path.GetTempFileName ();
-                               outwr = new StreamWriter (output);
-                               errwr = new StreamWriter (error);
-
                                ProcessStartInfo pinfo = new ProcessStartInfo (pathToTool, arguments);
                                pinfo.WorkingDirectory = GetWorkingDirectory () ?? Environment.CurrentDirectory;
 
@@ -146,19 +138,23 @@ namespace Microsoft.Build.Utilities
                                pendingLineFragmentError = new StringBuilder ();
 
                                try {
-                                       ProcessWrapper pw = ProcessService.StartProcess (pinfo, outwr, errwr, null, environmentOverride);
-                                       pw.OutputStreamChanged += (_, msg) => ProcessLine (pendingLineFragmentOutput, msg, StandardOutputLoggingImportance);
-                                       pw.ErrorStreamChanged += (_, msg) => ProcessLine (pendingLineFragmentError, msg, StandardErrorLoggingImportance);
-
-                                       pw.WaitForOutput (timeout == Int32.MaxValue ? -1 : timeout);
+                                       // When StartProcess returns, the process has already .Start()'ed
+                                       // If we subscribe to the events after that, then for processes that
+                                       // finish executing before we can subscribe, we won't get the output/err
+                                       // events at all!
+                                       ProcessWrapper pw = ProcessService.StartProcess (pinfo,
+                                                       (_, msg) => ProcessLine (pendingLineFragmentOutput, msg, StandardOutputLoggingImportance),
+                                                       (_, msg) => ProcessLine (pendingLineFragmentError, msg, StandardErrorLoggingImportance),
+                                                       null,
+                                                       environmentOverride);
+
+                                       pw.WaitForOutput (timeout == Int32.MaxValue ? Int32.MaxValue : timeout);
 
                                        // Process any remaining line
                                        ProcessLine (pendingLineFragmentOutput, StandardOutputLoggingImportance, true);
                                        ProcessLine (pendingLineFragmentError, StandardErrorLoggingImportance, true);
 
                                        exitCode = pw.ExitCode;
-                                       outwr.Close();
-                                       errwr.Close();
                                        pw.Dispose ();
                                } catch (System.ComponentModel.Win32Exception e) {
                                        Log.LogError ("Error executing tool '{0}': {1}", pathToTool, e.Message);
@@ -175,13 +171,6 @@ namespace Microsoft.Build.Utilities
                                return exitCode;
                        } finally {
                                DeleteTempFile (responseFileName);
-                               if (outwr != null)
-                                       outwr.Dispose ();
-                               if (errwr != null)
-                                       errwr.Dispose ();
-
-                               DeleteTempFile (output);
-                               DeleteTempFile (error);
                        }
                }