RFR: 8294899: Process.waitFor() throws IllegalThreadStateException when a process on Windows returns an exit code of 259
Jaikiran Pai
jpai at openjdk.org
Mon Oct 17 05:37:58 UTC 2022
On Wed, 12 Oct 2022 16:30:07 GMT, Roger Riggs <rriggs at openjdk.org> wrote:
> Process.waitFor() throws IllegalThreadStateException when a process returns an exit code of 259.
> As described in the bug report, `waitFor()` should not be sensitive to the exit value.
> Previously, it erroneously threw IllegalStateException.
> Added a test to verify.
Hello Roger,
The `Process.waitFor()` documentation states:
>
>Causes the current thread to wait, if necessary, until the process represented by this {@code Process} object has terminated.
So the implementation is expected to wait until the process has terminated. The Windows implementation of `waitFor` calls the JNI function `waitForInterruptibly`. The JNI implementation of `waitForInterruptibly` is:
HANDLE events[2];
events[0] = (HANDLE) handle;
events[1] = JVM_GetThreadInterruptEvent();
if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
FALSE, /* Wait for ANY event */
INFINITE) /* Wait forever */
== WAIT_FAILED)
win32Error(env, L"WaitForMultipleObjects");
So it calls a Windows native function called `WaitForMultipleObjects` and passes it 2 handles to wait on - one is the process handle and another for thread interrupt event. `FALSE` is passed as the `bWaitAll` param, which effectively means wait for either the process exit or the thread interrupt event.
The documentation of this Windows native API `WaitForMultipleObjects` states https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitformultipleobjects:
>
>If bWaitAll is FALSE, the return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects.
In our JNI implementation of `waitForInterruptibly` we appear to only check for the `WAIT_FAILED` but don't seem to check which handle satisfied the wait. Do you think it's possible that the process didn't yet terminate and instead the thread interrupt event was signalled? Should this `waitForInterruptibly` do those additional checks?
Does that perhaps explain why a subsequent call to Windows native `GetExitCodeProcess` function returns `STILL_ACTIVE` (the 259 exit code) which as per that functions documentation states https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
>
>If the process has not terminated and the function succeeds, the status returned is STILL_ACTIVE
-------------
PR: https://git.openjdk.org/jdk/pull/10680
More information about the core-libs-dev
mailing list