On Fri, 6 Mar 2026 14:28:46 GMT, Roger Riggs <[email protected]> wrote:

> Separately, I've a report of failures on a JDK 21 and JDK 17 build on Ubuntu 
> 25-10 with the same tests in Basic.java failing though only with exitcode 1 
> (not zero). That would be an older version of the launch protocol and 
> mechanism.
> 
> ```
> testJDK_os.arch=amd64
> testJDK_os.name=Linux
> testJDK_os.version=6.17.0-1003-oracle
> ```

I believe I figured out what happens, but I would like to prove it. Its 
actually a funny bug:

Let's say parent has only 1, 2, 3 open. We do 
ProcessBuilder.inheritIO().start().

Now lets say, childenv pipe gets 4 and 5, fail pipe gets 6 and 7.

We do these dup2 actions in the child process after forking:

https://github.com/openjdk/jdk/pull/29939/changes#diff-ffbcab6325b2ae4b57a81e39c51c155cb2dab372bc915060dfc47159c345797fR646-R647

We first dup2 fail[1] to "4". Now we have overwritten childenv[0], which now 
also points to the fail pipe write end.
We then dup2 childenv[0] to "5", but it's actually the fail pipe write end we 
copy. So now, both 4 and 5 point to fail pipe write end. We try to read from 5 
(the childenv[0]) in jspawnhelper to receive the ChildStuff structure from the 
parent. But since this is actually a copy of fail pipe write descriptor, I 
guess the read() fails immediately. So then we report "ERR_PIPE" via 4 (the 
real fail pipe write end), and this is what we see in the parent ("Failed.. 
(2)").

Whether this happens depends on luck, whether we get file descriptors <5 when 
creating a pipe. The old code did not do dup2 for fail and childenv, instead 
passing them via command line parameter. I kind of like the new way better, and 
will think about a way to circumvent the problem.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/29939#issuecomment-4012489335

Reply via email to