René's URL Explorer Experiment


Title: fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537… by ZanDev32 · Pull Request #1542 · processing/processing4 · GitHub

Open Graph Title: fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537… by ZanDev32 · Pull Request #1542 · processing/processing4

X Title: fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537… by ZanDev32 · Pull Request #1542 · processing/processing4

Description: Fix: 3D/OpenGL sketches crash with UnsatisfiedLinkError on Linux — jspawnhelper missing exec permission Closes #1537 Summary 3D/OpenGL sketches (P3D, P2D, OBJ-loading, anything using JOGL) crashed on launch with UnsatisfiedLinkError. The cause was lib/jspawnhelper losing its executable permission during the includeJdk Gradle 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 Warning: Caught Exception while retrieving executable temp base directory: java.io.IOException: Could not determine a temporary executable directory at com.jogamp.common.util.IOUtil.getTempDir(IOUtil.java:1401) at com.jogamp.common.util.cache.TempFileCache.(TempFileCache.java:84) at com.jogamp.common.os.Platform$1.run(Platform.java:313) java.lang.UnsatisfiedLinkError: 'boolean jogamp.common.jvm.JVMUtil.initialize(java.nio.ByteBuffer)' at jogamp.common.jvm.JVMUtil.initialize(Native Method) at com.jogamp.common.os.Platform.(Platform.java:290) at com.jogamp.opengl.GLProfile.(GLProfile.java:151) at processing.opengl.PSurfaceJOGL.initGL(PSurfaceJOGL.java:204) A library used by this sketch relies on native code that is not available. 2D sketches (Java2D renderer) ran fine because they never call Runtime.exec(). Root cause jspawnhelper is a small ELF binary at lib/jspawnhelper that JDK 17's ProcessImpl execs (via vfork + execve) to spawn child processes. The includeJdk Gradle task copied the JDK into resources/jdk/ but ran its file-permission loop at configuration time, before the copy happened, on an empty directory. The loop set writable and readable but never executable. Since the directory was empty at config time, no files were affected. The Gradle Copy task's dirPermissions spec only applied to directories, not files. Result: jspawnhelper (and jexec, and everything in bin/) landed with mode 0644 instead of 0755. When the sketch JVM tried to exec jspawnhelper, the kernel returned EACCES (error=13, Permission denied). This broke every Runtime.exec() call in the sketch process. JOGL's IOUtil.testDirExec() writes a test script to a temp directory and actually execve()s it to validate that the temp dir allows execution. With jspawnhelper non-executable, that test failed for every candidate directory, so TempJarCache never initialized, native libraries were never extracted, and the sketch crashed with UnsatisfiedLinkError. 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: File Fresh (working) Bundled (broken) lib/jspawnhelper 0755 0644 lib/jexec 0755 0644 lib/server/classes.jsa 0444 0644 jspawnhelper was the critical one. chmod 755 jspawnhelper on the bundled JDK immediately fixed Runtime.exec(). Why includeJdk didn't preserve the exec bit The original code: tasks.register("includeJdk") { from(Jvm.current().javaHome.absolutePath) destinationDir = composeResources("jdk").get().asFile dirPermissions { unix("rwx------") } fileTree(destinationDir).files.forEach { file -> // runs at CONFIG time, on EMPTY dir file.setWritable(true, false) file.setReadable(true, false) // no setExecutable() } } The fileTree(destinationDir).files.forEach block ran at Gradle configuration time, before the Copy task executed. destinationDir was empty, so the loop processed zero files. Even if it had run after the copy, it only set writable and readable, never executable. The dirPermissions spec only applied to directories. The fix app/build.gradle.kts — includeJdk task (root cause) Moved the permission loop into a doLast block (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 — setExecutablePermissions task (belt and suspenders) Added **/runtime/**/bin/** and **/runtime/**/lib/** patterns so the IDE runtime's jspawnhelper is also covered: include("**/runtime/**/bin/**") include("**/runtime/**/lib/**") app/src/processing/app/Platform.java — JAVA_HOME / JDK_HOME support (Extra) Added env var checks inside the existing "If the JDK is set in the environment" fallback block, before the java.home system property fallback. This lets users override the sketch JDK when the bundled resources/jdk is absent (e.g., portable installs without a bundled JDK): for (String envKey : new String[] { "JAVA_HOME", "JDK_HOME" }) { String envPath = System.getenv(envKey); if (envPath != null && !envPath.isEmpty()) { File envHome = new File(envPath); if (new File(envHome, "bin/java" + (Platform.isWindows() ? ".exe" : "")).canExecute()) { return envHome; } } } The bundled resources/jdk still takes priority. JAVA_HOME/JDK_HOME is only checked when the bundle is missing. Tests Test sketch: a P3D project that loads an .obj file (Rubik's cube model with loadShape()). Scenario JAVA_HOME Expected Result Normal usage (jspawnhelper fixed) not set Sketch runs PASS — Finished. exit 0 JAVA_HOME = system JDK 21 set, valid Sketch runs (bundle wins) PASS — Finished. exit 0 JAVA_HOME = invalid path set, invalid Sketch runs (bundle wins) PASS — Finished. exit 0 JDK_HOME = system JDK 21 set, valid Sketch runs (bundle wins) PASS — Finished. exit 0 All tests run with processing cli --sketch= --run automatically using Kimi K2.7 Code under my watch . The X11Util.Display shutdown messages in the output confirm JOGL/OpenGL initialized and rendered before clean exit. Before the fix (jspawnhelper 0644), the same sketch crashed with UnsatisfiedLinkError: 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 Arch Linux, kernel 7.0.5-arch1-1-g14 Processing 4.5.5 (rev 1433) Bundled sketch JDK: Temurin 17.0.19+10 System JDK: OpenJDK 21.0.11 JOGL / gluegen 2.6.0

Open Graph Description: Fix: 3D/OpenGL sketches crash with UnsatisfiedLinkError on Linux — jspawnhelper missing exec permission Closes #1537 Summary 3D/OpenGL sketches (P3D, P2D, OBJ-loading, anything using JOGL) crashed ...

X Description: Fix: 3D/OpenGL sketches crash with UnsatisfiedLinkError on Linux — jspawnhelper missing exec permission Closes #1537 Summary 3D/OpenGL sketches (P3D, P2D, OBJ-loading, anything using JOGL) crashed ...

Opengraph URL: https://github.com/processing/processing4/pull/1542

X: @github

direct link

Domain: github.com

route-pattern/:user_id/:repository/pull/:id/files(.:format)
route-controllerpull_requests
route-actionfiles
fetch-noncev2:8de966f5-790b-357f-e8fd-b772067a030a
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-idE8D2:7152C:162FF9E:1F7EBFA:6A5FA6B5
html-safe-nonce39a16d7f6695837f6cb5d25ac66f4b6f34453672fad671a332c9407b9c26d5ca
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFOEQyOjcxNTJDOjE2MkZGOUU6MUY3RUJGQTo2QTVGQTZCNSIsInZpc2l0b3JfaWQiOiI3NjAxNjQxOTk4ODM3MDY1Mzk3IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0=
visitor-hmacbf01f19c6a92cea2a217a50e4b3ff198be8ca24929a7cda1b9ae1f47c2b6594c
hovercard-subject-tagpull_request:4023158908
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/files
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/processing/processing4/pull/1542/files
twitter:imagehttps://avatars.githubusercontent.com/u/52073144?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/52073144?s=400&v=4
og:image:altFix: 3D/OpenGL sketches crash with UnsatisfiedLinkError on Linux — jspawnhelper missing exec permission Closes #1537 Summary 3D/OpenGL sketches (P3D, P2D, OBJ-loading, anything using JOGL) crashed ...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
None9b835c054d57dfb6ce72ba8f0eb8f16f0370860631609eb10df818738c61c68d
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/processing/processing4 git https://github.com/processing/processing4.git
octolytics-dimension-user_id1617169
octolytics-dimension-user_loginprocessing
octolytics-dimension-repository_id844382769
octolytics-dimension-repository_nwoprocessing/processing4
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id844382769
octolytics-dimension-repository_network_root_nwoprocessing/processing4
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbotrue
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release4df9bc0bde4bfd7cd95e75afdd7f103984ece3a1
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/processing/processing4/pull/1542/files#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fprocessing%2Fprocessing4%2Fpull%2F1542%2Ffiles
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
Code QualityEnforce quality at mergehttps://github.com/features/code-quality
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fprocessing%2Fprocessing4%2Fpull%2F1542%2Ffiles
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Ffiles&source=header-repo&source_repo=processing%2Fprocessing4
Reloadhttps://github.com/processing/processing4/pull/1542/files
Reloadhttps://github.com/processing/processing4/pull/1542/files
Reloadhttps://github.com/processing/processing4/pull/1542/files
Please reload this pagehttps://github.com/processing/processing4/pull/1542/files
processing https://github.com/processing
processing4https://github.com/processing/processing4
Please reload this pagehttps://github.com/processing/processing4/pull/1542/files
Notifications https://github.com/login?return_to=%2Fprocessing%2Fprocessing4
Fork 175 https://github.com/login?return_to=%2Fprocessing%2Fprocessing4
Star 444 https://github.com/login?return_to=%2Fprocessing%2Fprocessing4
Code https://github.com/processing/processing4
Issues 249 https://github.com/processing/processing4/issues
Pull requests 26 https://github.com/processing/processing4/pulls
Actions https://github.com/processing/processing4/actions
Projects https://github.com/processing/processing4/projects
Wiki https://github.com/processing/processing4/wiki
Security and quality 0 https://github.com/processing/processing4/security
Insights https://github.com/processing/processing4/pulse
Code https://github.com/processing/processing4
Issues https://github.com/processing/processing4/issues
Pull requests https://github.com/processing/processing4/pulls
Actions https://github.com/processing/processing4/actions
Projects https://github.com/processing/processing4/projects
Wiki https://github.com/processing/processing4/wiki
Security and quality https://github.com/processing/processing4/security
Insights https://github.com/processing/processing4/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fprocessing%2Fprocessing4%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fprocessing%2Fprocessing4%2Fissues%2Fnew%2Fchoose
ZanDev32https://github.com/ZanDev32
processing:mainhttps://github.com/processing/processing4/tree/main
ZanDev32:fix/jspawnhelper-exec-permission-1537https://github.com/ZanDev32/processing4/tree/fix/jspawnhelper-exec-permission-1537
Conversation 2 https://github.com/processing/processing4/pull/1542
Commits 1 https://github.com/processing/processing4/pull/1542/commits
Checks 6 https://github.com/processing/processing4/pull/1542/checks
Files changed 2 https://github.com/processing/processing4/pull/1542/files
fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537… https://github.com/processing/processing4/pull/1542/files#top
Show all changes 1 commit https://github.com/processing/processing4/pull/1542/files
1a1db1c fix: preserve exec permissions on jspawnhelper in bundled JDK ([#1537… ZanDev32 Jul 9, 2026 https://github.com/processing/processing4/pull/1542/commits/1a1db1c8e1df948f984a8f3901c999e11838d0b5
Clear filters https://github.com/processing/processing4/pull/1542/files
Please reload this pagehttps://github.com/processing/processing4/pull/1542/files
Please reload this pagehttps://github.com/processing/processing4/pull/1542/files
build.gradle.kts https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
Platform.java https://github.com/processing/processing4/pull/1542/files#diff-3b521fa61cb834960d3a01b9696ae36885994c6b252ea5f1a0269db0ca129a30
app/build.gradle.ktshttps://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
View file https://github.com/processing/processing4/blob/1a1db1c8e1df948f984a8f3901c999e11838d0b5/app/build.gradle.kts
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/processing/processing4/pull/1542/{{ revealButtonHref }}
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
https://github.com/processing/processing4/pull/1542/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46
app/src/processing/app/Platform.javahttps://github.com/processing/processing4/pull/1542/files#diff-3b521fa61cb834960d3a01b9696ae36885994c6b252ea5f1a0269db0ca129a30
View file https://github.com/processing/processing4/blob/1a1db1c8e1df948f984a8f3901c999e11838d0b5/app/src/processing/app/Platform.java
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/processing/processing4/pull/1542/{{ revealButtonHref }}
https://github.com/processing/processing4/pull/1542/files#diff-3b521fa61cb834960d3a01b9696ae36885994c6b252ea5f1a0269db0ca129a30
https://github.com/processing/processing4/pull/1542/files#diff-3b521fa61cb834960d3a01b9696ae36885994c6b252ea5f1a0269db0ca129a30
https://github.com/processing/processing4/pull/1542/files#diff-3b521fa61cb834960d3a01b9696ae36885994c6b252ea5f1a0269db0ca129a30
Please reload this pagehttps://github.com/processing/processing4/pull/1542/files
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.