JDK-8294899 : Process.waitFor() throws IllegalThreadStateException when a process on Windows returns an exit code of 259
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 8,11,17,18,19,20
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows
  • CPU: x86_64
  • Submitted: 2022-10-05
  • Updated: 2022-10-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Description
ADDITIONAL SYSTEM INFORMATION :
Windows (any version), OpenJDK (any version)

A DESCRIPTION OF THE PROBLEM :
When a Java application spawns a process on Windows that returns an exit code of 259 (0x103), the call to `Process.waitFor()` throws an IllegalThreadStateException.

It does this because the implementation method, `waitFor()` in ProcessImpl.java, calls `exitValue()`. In turn, `exitValue()` checks if the exit value is 259, which on Windows is returned when the process has not yet exited. `exitValue()` then goes ahead and throws an exception.

This can easily be fixed by having `waitFor()` call `getExitCodeProcess()` directly, thus bypassing the check for "not yet exited" since we know it actually has exited. In other words, in https://github.com/openjdk/jdk/blob/master/src/java.base/windows/classes/java/lang/ProcessImpl.java, replace line 575, containing "return exitValue();", with "return getExitCodeProcess(handle);"

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a Process that exits with an exit value of 259 on Windows. Call process.waitFor().

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should return 259.
ACTUAL -
It throws an exception saying the process has not exited.

CUSTOMER SUBMITTED WORKAROUND :
There is no workaround, but it can be easily fixed in the JDK source.

FREQUENCY : always



Comments
A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/10680 Date: 2022-10-12 16:30:07 +0000
12-10-2022

The observations on Windows 10: JDK 8: Failed, IllegalThreadStateException thrown JDK 11: Failed. JDK 17: Failed. JDK 18: Failed. JDK 19: Failed. JDK 20ea+4: Failed.
06-10-2022

Additional information from the submitter: As requested, here is a self-contained reproducer. Save it to Demo.java, and run "javac Demo.java" followed by "java Demo" on any Windows machine. It should print "259" but instead it throws an exception. import java.io.IOException; public class Demo { public static void main(String[] args) throws IOException, InterruptedException { Process process = new ProcessBuilder("cmd", "/c", "exit /b 259").start(); int exitValue = process.waitFor(); System.out.println(exitValue); } }
06-10-2022

Requested a simple reproducer from the submitter.
06-10-2022

Changing the semantics as suggested by the reporter might be risky, as the code of the Windows impl of exitValue() goes back at least 15 years.
06-10-2022