From 7d5058577fef1619bfb3661b1f10f324750440f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 18 Dec 2025 13:32:47 +0100 Subject: [PATCH 1/2] Use UncaughtExceptionHandler for common pool usage in image builder --- substratevm/mx.substratevm/mx_substratevm.py | 1 + .../CommonPoolUncaughtExceptionHandler.java | 49 +++++++++++++++++++ .../hosted/NativeImageGeneratorRunner.java | 7 +++ 3 files changed, 57 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/CommonPoolUncaughtExceptionHandler.java diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index c8722d98887f..9106a19cd35a 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -2536,6 +2536,7 @@ def compute_graal_compiler_flags_map(self): '-Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime', # use truffle interpreter as fallback '-Dgraalvm.ForcePolyglotInvalid=true', # use PolyglotInvalid PolyglotImpl fallback (when --tool:truffle is not used) '-Dgraalvm.locatorDisabled=true', + '-Djava.util.concurrent.ForkJoinPool.common.exceptionHandler=com.oracle.svm.hosted.CommonPoolUncaughtExceptionHandler', ] if mx.get_os() == 'linux': libc = mx.get_os_variant() if mx.get_os_variant() else 'glibc' diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/CommonPoolUncaughtExceptionHandler.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/CommonPoolUncaughtExceptionHandler.java new file mode 100644 index 000000000000..e87512f95548 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/CommonPoolUncaughtExceptionHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.hosted; + +import java.lang.Thread.UncaughtExceptionHandler; +import java.util.concurrent.ForkJoinPool; + +import com.oracle.svm.core.util.ExitStatus; + +/** + * An uncaught exception handler for the {@linkplain ForkJoinPool#commonPool() common pool} as used + * in the context of image building. This handler is responsible for immediate abort in the case of + * uncaught exceptions in any thread managed by the common pool. The native-image driver installs it + * by setting the {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} system property. + * Failure to install this handler is detected to ensure we can rely on every image build being + * performed with this handler enabled. See {@link NativeImageGeneratorRunner#main(String[])}. + */ +public class CommonPoolUncaughtExceptionHandler implements UncaughtExceptionHandler { + + @Override + public synchronized void uncaughtException(Thread t, Throwable e) { + System.err.print("Aborting image build. Uncaught Exception in thread " + t + ' '); + e.printStackTrace(System.err); + System.exit(ExitStatus.BUILDER_ERROR.getValue()); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 559cd421903f..c145cb19d4f4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -42,6 +42,7 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.TimerTask; +import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; import org.graalvm.collections.Pair; @@ -110,6 +111,12 @@ public static void main(String[] args) { List providers = new ArrayList<>(); ServiceLoader.load(NativeImageGeneratorRunnerProvider.class).forEach(providers::add); + var ueh = ForkJoinPool.commonPool().getUncaughtExceptionHandler(); + if (!(ueh instanceof CommonPoolUncaughtExceptionHandler)) { + VMError.shouldNotReachHere("Unable to install " + CommonPoolUncaughtExceptionHandler.class.getName() + + " via java.util.concurrent.ForkJoinPool.commonPool.exceptionHandler system property"); + } + if (providers.isEmpty()) { new NativeImageGeneratorRunner().start(args); } else { From 1d525c884251462d146a2a235c57c757010af53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 18 Dec 2025 15:43:28 +0100 Subject: [PATCH 2/2] Add missing NI config for jdk.graal.compiler.test --- .../native-image/jdk.graal.compiler.test/native-image.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 compiler/src/jdk.graal.compiler.test/src/META-INF/native-image/jdk.graal.compiler.test/native-image.properties diff --git a/compiler/src/jdk.graal.compiler.test/src/META-INF/native-image/jdk.graal.compiler.test/native-image.properties b/compiler/src/jdk.graal.compiler.test/src/META-INF/native-image/jdk.graal.compiler.test/native-image.properties new file mode 100644 index 000000000000..6de58bc83ef7 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/META-INF/native-image/jdk.graal.compiler.test/native-image.properties @@ -0,0 +1 @@ +Args = --add-exports=org.graalvm.sl/com.oracle.truffle.sl.builtins=ALL-UNNAMED