Hi Thomas,
Thank you for this quick fix!
I have tested (after much difficultly getting cross compilation to work
- a good learning experience) and this fix works for me. Using
QEMU_STRACE, I verified that argv[0] is now the program name and argv[1]
contains the fd data.
While you are correct, that changes to jspawnhelper aren't needed (since
it uses argv[argc-1]), you may want to update this comment here:
https://github.com/openjdk/jdk/blob/959a61fdd483c9523764b9ba0972f59ca06db0ee/src/java.base/unix/native/jspawnhelper/jspawnhelper.c#L139
-DJ
On 6/17/2023 16:43, Thomas Stüfe wrote:
Mind testing https://github.com/openjdk/jdk/pull/14531 ?
On Sat, Jun 17, 2023 at 8:20 PM Thomas Stüfe <thomas.stu...@gmail.com>
wrote:
Hi Daniel,
thank you for that thorough analysis. I opened
https://bugs.openjdk.org/browse/JDK-8310265 to track this issue.
Looking at the code, this should be easy to fix, we would not even
have to fix jspawnhelper itself, just its spawn point.
I did a small patch which seemed to work. But this code is
notorious for being tricky and I may overlooking something. Lets see.
Cheers, Thomas
On Sat, Jun 17, 2023 at 6:33 AM Daniel Jarabek
<jarabe...@gmail.com> wrote:
Hi,
While trying to run jshell in qemu-user-static using binfmt_misc
(specifically, using this docker based tool [1]), I ran into
an issue.
Jshell would fail to start and print `This command is not for
general
use and should only be run as the result of a call to
ProcessBuilder.start() or Runtime.exec() in a java
application` along
with a stack trace including `Failed to exec spawn helper`. After
searching this error, I found JDK-8296001 [2]. This issue
presented a
very similar scenario (using a userspace architecture
emulator). I
looked into this issue and I believe I have identified the
root cause.
My specific investigation was done around jdk17, but this
issue also
occurs on jdk20 and older jdk versions (though it seems like
the "spawn"
strategy is not used by default on linux with jdk 8 and 11).
Note: I use argv0 to refer to "argv[0]" to prevent confusion
with footnotes.
Traditionally, argv0 contains the name of the program being
executed.
While this is more a convention than anything [3], it is very
widely
used. jspawnhelper [4] is an executable used to assist in
launching
processes via ProcessBuilder and Runtime.exec. Unlike the
convention,
jspawnhelper uses argv0 for passing data [5]. When
binfmts_misc [6]
executes an interpreter, it overwrites argv0, unless a flag is
set. This
causes jspawnhelper to fail to parse argv0 (since it's the
application
path, and not the data sent by the JDK), so it prints the
warning about
not being for general use. By setting the binfmt_misc `P`
(preserve-argv0) flag, it preserves argv0 which fixes this
problem.
Since qemu-user correctly supports this flag, all I had to do
to fix the
issue in my case was run qemu-binfmt-conf.sh with
`--preserve-argv0 yes`
to set that flag. It's likely that in the case of the above
issue, the
same problem is occurring and it may have a similar
resolution. This
could be fixed in OpenJDK by using argv1 instead, but at least
in my
case of binfmts_misc, this is an external configuration issue
that can
be easily fixed. However, I would appreciate it if someone with
permission could comment on the above issue with a link to
this email
for anyone who runs into this in the future.
-DJ
[1] https://github.com/multiarch/qemu-user-static
[2] https://bugs.openjdk.org/browse/JDK-8296001
[3] https://stackoverflow.com/a/2051031
[4]
https://github.com/openjdk/jdk/blob/master/src/java.base/unix/native/jspawnhelper/jspawnhelper.c
[5]
https://github.com/openjdk/jdk/blob/bcc4d36857b0907e865d0afc4447f9b0780f8101/src/java.base/unix/native/libjava/ProcessImpl_md.c#L498-L500
[6] https://docs.kernel.org/admin-guide/binfmt-misc.html