[Process] Do not use Exited as it's racy with Start and BeginOutputReadLine/BeginErro...
authorLudovic Henry <ludovic@xamarin.com>
Fri, 16 Oct 2015 17:31:19 +0000 (18:31 +0100)
committerLudovic Henry <ludovic@xamarin.com>
Fri, 16 Oct 2015 17:41:45 +0000 (18:41 +0100)
commit7c5c5f494058806046506912bdd1a3d91ae1662d
treeefbfd8b9ff6356a5dd1d040448b28fe540269df9
parent372658a28e3c41ac3db96d0249636192bdc8b28c
[Process] Do not use Exited as it's racy with Start and BeginOutputReadLine/BeginErrorReadLine

The issue can arise if the Process is going to run faster than the call
between Start and BeginOutputReadLine/BeginErrorReadLine. To increase
the chance of the race happening, insert a Thread.Sleep (1000) between
Start and BeginOutputReadLine/BeginErrorReadLine.

This race exists because the WaitForExit in the background thread in the
Process, will first wait the process to finish, then try to wait for the
output to finish, but it will be null as BeginOutputReadLine has not been
called yet, then try to wait on error (same issue as output), and finally
call the Exited event, which will close the stdout and stderr TextWriter.
The call to BeginOutputReadLine and BeginErrorReadLine will finally happen
(which is still correct as the output and error of the Process has not
been closed yet), then calling the OutputDataReceived and ErrorDataReceived
callbacks which will try to write to the closed stdout and stderr
TextWriter.

Simply enqueuing a ThreadPool work item, which will wait for the process
to exit manually, simply resolve this issue, as we guarantee that the
call to WaitForExit happens after BeginOutputReadLine/BeginErrorReadLine,
and is not racing with it.
mono/tests/test-runner.cs