Merge pull request #2646 from ludovic-henry/fix-processwatch-dispose
authorAnkit Jain <radical@gmail.com>
Mon, 22 Feb 2016 18:26:24 +0000 (13:26 -0500)
committerAnkit Jain <radical@gmail.com>
Mon, 22 Feb 2016 18:26:24 +0000 (13:26 -0500)
[Microsoft.Build] Fix XS build error + Fix expected output newline from ProcessWrapper.OutputStreamChanged and ProcessWrapper.ErrorStreamChanged

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

index d78c1eba66d1ac49a666544dfcf9612a953fb5ae..1674ff8b5dc3095f027cd6ffd60d1562e5e056d4 100644 (file)
@@ -13,6 +13,7 @@ namespace Microsoft.Build.Utilities
                ManualResetEvent endEventErr = new ManualResetEvent (false);
                ManualResetEvent endEventExit = new ManualResetEvent (false);
                bool done;
+               bool disposed;
                object lockObj = new object ();
 
                public ProcessWrapper ()
@@ -26,29 +27,41 @@ namespace Microsoft.Build.Utilities
                        base.EnableRaisingEvents = true;
 
                        base.Exited += (s, args) => {
-                               endEventExit.Set ();
+                               try {
+                                       endEventExit.Set ();
+                                       WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr });
+                               } catch (ObjectDisposedException) {
+                                       return; // we already called Dispose
+                               }
 
-                               WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr });
                                OnExited (this, EventArgs.Empty);
                        };
 
                        base.OutputDataReceived += (s, args) => {
                                if (args.Data == null) {
-                                       endEventOut.Set ();
+                                       try {
+                                               endEventOut.Set ();
+                                       } catch (ObjectDisposedException) {
+                                               return; // we already called Dispose
+                                       }
                                } else {
                                        ProcessEventHandler handler = OutputStreamChanged;
                                        if (handler != null)
-                                               handler (this, args.Data);
+                                               handler (this, args.Data + Environment.NewLine);
                                }
                        };
 
                        base.ErrorDataReceived += (s, args) => {
                                if (args.Data == null) {
-                                       endEventErr.Set ();
+                                       try {
+                                               endEventErr.Set ();
+                                       } catch (ObjectDisposedException) {
+                                               return; // we already called Dispose
+                                       }
                                } else {
                                        ProcessEventHandler handler = ErrorStreamChanged;
                                        if (handler != null)
-                                               handler (this, args.Data);
+                                               handler (this, args.Data + Environment.NewLine);
                                }
                        };
 
@@ -71,24 +84,28 @@ namespace Microsoft.Build.Utilities
 
                protected override void Dispose (bool disposing)
                {
-                       lock (lockObj) {
-                               if (endEventOut == null)
-                                       return;
-                       }
+                       if (disposed)
+                               return;
 
                        if (!done)
                                ((IAsyncOperation)this).Cancel ();
 
+                       // if we race with base.Exited, we don't want to hang on WaitAll (endEventOut, endEventErr)
+                       endEventOut.Set ();
+                       endEventErr.Set ();
+
                        endEventOut.Close ();
                        endEventErr.Close ();
                        endEventExit.Close ();
 
+                       disposed = true;
+
                        base.Dispose (disposing);
                }
 
                void CheckDisposed ()
                {
-                       if (endEventOut == null)
+                       if (disposed)
                                throw new ObjectDisposedException ("ProcessWrapper");
                }