jspawnhelper's sometimes problematic use of argv0
Daniel Jarabek
jarabekit at gmail.com
Sat Jun 17 04:33:42 UTC 2023
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
More information about the core-libs-dev
mailing list