fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537…#1542
fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537…#1542ZanDev32 wants to merge 1 commit into
Conversation
|
Hi @ZanDev32 and thanks for the PR. Before we review it further, could you please read our AI_USAGE_POLICY.md? Also, in the issue (#1537), you mention using AI agents to identify the problem. Could you clarify what parts of the investigation, implementation, and testing were your own work, and what parts were assisted by AI? Please write your response yourself rather than having an AI agent generate it. You may use an LLM for proofreading or translation, but we'd like to understand your own reasoning and contribution. |
…ssing#1537](processing#1537)) Fix: - Move the permission loop in includeJdk into a doLast block so it runs after the copy, and re-apply the exec bit from the source JDK for files that should be executable. - Extend setExecutablePermissions to also cover the IDE runtime/ path (not just resources/), since the runtime's jspawnhelper had the same issue. - Add JAVA_HOME / JDK_HOME env var support in Platform.getJavaHome(), inside the existing "If the JDK is set in the environment" fallback block, so users can point Processing at a different JDK when the bundle is absent.
9db42a6 to
1a1db1c
Compare
I already updated the original PR message and rebased to match the latest commit. All of the contents in that message have been reviewed by me and tested using an actual project, both with the graphical IDE and the CLI. At the end of the day, it's just a permission problem, nothing big. I also added a fix so the app uses the system Java instead of the built-in one (this was the original solution). Actually, this "extra" feature was already implemented before in PR #1199, but it doesn't work correctly anymore on the latest version of Processing (it doesn't work on either Windows 11 or Arch Linux with Wayland on kernel 7.0.5). |
Fix: 3D/OpenGL sketches crash with
UnsatisfiedLinkErroron Linux —jspawnhelpermissing exec permissionCloses #1537
Summary
3D/OpenGL sketches (P3D, P2D, OBJ-loading, anything using JOGL) crashed on launch with
UnsatisfiedLinkError. The cause waslib/jspawnhelperlosing its executable permission during theincludeJdkGradle copy task. Without the exec bit, the bundled JDK could not fork+exec child processes, which broke JOGL's temp-directory validation and prevented native libraries from loading.The crash
2D sketches (Java2D renderer) ran fine because they never call
Runtime.exec().Root cause
jspawnhelperis a small ELF binary atlib/jspawnhelperthat JDK 17'sProcessImplexecs (viavfork+execve) to spawn child processes. TheincludeJdkGradle task copied the JDK intoresources/jdk/but ran its file-permission loop at configuration time, before the copy happened, on an empty directory. The loop setwritableandreadablebut neverexecutable. Since the directory was empty at config time, no files were affected. The GradleCopytask'sdirPermissionsspec only applied to directories, not files. Result:jspawnhelper(andjexec, and everything inbin/) landed with mode0644instead of0755.When the sketch JVM tried to exec
jspawnhelper, the kernel returnedEACCES(error=13, Permission denied). This broke everyRuntime.exec()call in the sketch process. JOGL'sIOUtil.testDirExec()writes a test script to a temp directory and actuallyexecve()s it to validate that the temp dir allows execution. Withjspawnhelpernon-executable, that test failed for every candidate directory, soTempJarCachenever initialized, native libraries were never extracted, and the sketch crashed withUnsatisfiedLinkError.The same issue affected the IDE runtime at
lib/runtime/lib/jspawnhelper.How I found it
I used Kimi K2.7 Code to help find the root cause. This took several wrong turns before the actual cause surfaced. After I tried everything, i finally decided to just compare the Build-In JDK with a fresh Temurin 17 from Adoptium file by file. It turn out that there are some file that have difference permission:
lib/jspawnhelper07550644lib/jexec07550644lib/server/classes.jsa04440644jspawnhelperwas the critical one.chmod 755 jspawnhelperon the bundled JDK immediately fixedRuntime.exec().Why
includeJdkdidn't preserve the exec bitThe original code:
The
fileTree(destinationDir).files.forEachblock ran at Gradle configuration time, before theCopytask executed.destinationDirwas empty, so the loop processed zero files. Even if it had run after the copy, it only setwritableandreadable, neverexecutable. ThedirPermissionsspec only applied to directories.The fix
app/build.gradle.kts—includeJdktask (root cause)Moved the permission loop into a
doLastblock (runs after the copy) and re-applied the exec bit from the source JDK for files that should be executable:doLast { fileTree(destinationDir).files.forEach { file -> val sourceFile = File(Jvm.current().javaHome.absolutePath, file.relativeTo(destinationDir).path) if (sourceFile.canExecute()) { file.setExecutable(true, false) } file.setWritable(true, false) file.setReadable(true, false) } }app/build.gradle.kts—setExecutablePermissionstask (belt and suspenders)Added
**/runtime/**/bin/**and**/runtime/**/lib/**patterns so the IDE runtime'sjspawnhelperis also covered:app/src/processing/app/Platform.java—JAVA_HOME/JDK_HOMEsupport (Extra)Added env var checks inside the existing "If the JDK is set in the environment" fallback block, before the
java.homesystem property fallback. This lets users override the sketch JDK when the bundledresources/jdkis absent (e.g., portable installs without a bundled JDK):The bundled
resources/jdkstill takes priority.JAVA_HOME/JDK_HOMEis only checked when the bundle is missing.Tests
Test sketch: a P3D project that loads an
.objfile (Rubik's cube model withloadShape()).JAVA_HOMEFinished.exit 0JAVA_HOME= system JDK 21Finished.exit 0JAVA_HOME= invalid pathFinished.exit 0JDK_HOME= system JDK 21Finished.exit 0All tests run with
processing cli --sketch=<path> --runautomatically using Kimi K2.7 Code under my watch . TheX11Util.Displayshutdown messages in the output confirm JOGL/OpenGL initialized and rendered before clean exit.Before the fix (jspawnhelper
0644), the same sketch crashed withUnsatisfiedLinkError: JVMUtil.initialize. So this pr are tested, and verified solves the issue without side effects so far.tbh this is just a small change covering 2 files changed, 29 insertions(+), and 4 deletions(-).
Environment