2008-04-12

Process.WaitForExit(): just 25 days, but it feels like forever

There's a curious little bug in the Process class that you're not likely to hit any time soon, but someone encountered it nevertheless: Process.WaitForExit() will wait for the process to terminate or until 2 147 483 647 milliseconds have passed, whichever occurs first. So if the process you're observing still hasn't terminated after some 25 days, the call will return anyway.

This is contrary to the documentation, which states that Process.WaitForExit() is supposed to wait indefinitely. And 2 147 483 647, of course, is the magic value 0x7fffffff. What's going wrong?

It's actually very simple: Process.WaitForExit() calls WaitForSingleObject(..., Int.MaxValue) on the process handle, and Int.MaxValue is of course 0x7fffffff. But if you read the documentation for WaitForSingleObject(), it clearly states that an infinite wait is supposed to use INFINITE, which is defined as (DWORD) -1, or 0xffffffff. In other words, a simple programming error on behalf of whoever wrote the Process class.

Interestingly, the documentation for the overload Process.WaitForExit(int milliseconds) even clarifies the erroneous thought process used: "The amount of time, in milliseconds, to wait for the associated process to exit. The maximum is the largest possible value of a 32-bit integer, which represents infinity to the operating system." That should have been "the largest possible value of an unsigned 32-bit integer", a small but rather important difference.

The easiest way to work around this bug is to call Process.WaitForExit(Timeout.Infinite) instead, since Timeout.Infinite does have the correct value. You should then follow up this call with Process.WaitForExit(), because that call will correctly wait for any redirected I/O to finish (which the overload will not do).

No comments: