Mono Process bug

Calling System.Diagnostics.Process.WaitForExit() shortly after a Java.Lang.Process has run often hangs despite the process having finished.

I've attached a simple demonstration Xamarin.Android project that exhibits this behaviour. It invokes the 'id' terminal command using System.Diagnostics.Process ten times, then it invokes the same command using Java.Lang.Process, then it repeats the System.Diagnostics.Process invocation ten times. Pressing the button on the UI will invoke this sequence of commands and the results will come out in logcat or the application output window.

The 'id' command is deterministic and we would expect the process calls to terminate quickly, however, about 20% of the time, one or more of the System.Diagnostic.Process calls hangs on WaitForExit, which has a five second timeout. In all cases, the command appears to have actually completed because 'ps' does not report it being active and the input buffer contains the expected data and has been read to the end of the stream.

The failure mode only occurs if you have already run Java.Lang.Process and seems to sort itself out after a small number of failures (typically two). If you comment out the invocation of Java.Lang.Process, the problem never occurs.

Our working theory is that both methods for Process invocation rely on a common pool of resources, possibly handles, and that this pool becomes temporarily corrupted. It isn't obviously thread related as each invocation runs sequentially.

Other evidence of interest includes the occasional hang of Java.Lang.Process.WaitFor() under similar circumstances. It is commented out in the attached example project because the timeout of WaitForExit makes for a cleaner demonstration. Add it back and you should see it hang with the same frequency as WaitForExit was experiencing timeouts. Similarly, removing calls to System.Diagnostics.Process make the problem go away, which implies it's something to do with the interplay between the both of them.

The problems occurs on at least five different Android devices using a range of processors and Android 4.2.2 and Android 5.0.1.

It should be noted that this hang is unlikely to be the "forgot to empty all the buffer streams" problem that is a common source of process hang behaviour because all the input and error streams are merged and the streams are read to EOF in all cases.

Here is the expected output:

TEST START ------------------
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS JAVA: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
TEST END ------------------

...and here is the common fail mode...

TEST START ------------------
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS JAVA: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
FAILURE MONO: TIMEOUT!
FAILURE MONO: TIMEOUT!
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
SUCCESS MONO: uid=10084(u0_a84) gid=10084(u0_a84) groups=1028(sdcard_r),3003(inet),50084(all_a84)
TEST END ------------------
Sign In or Register to comment.