-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Describe GraalVM and your environment :
- GraalVM version or commit id if built from source: 21+35-jvmci-23.1-b15
- CE or EE: CE
- JDK version: JDK21
- OS and OS Version: Ubuntu
- Architecture: amd64
- The output of
java -Xinternalversion:
~/bin/graalvm-community-openjdk-21+35.1/bin/java -Xinternalversion
OpenJDK 64-Bit Server VM (21+35-jvmci-23.1-b15) for linux-amd64 JRE (21+35-jvmci-23.1-b15), built on 2023-09-05T16:45:14Z by "buildslave" with gcc 11.2.0
Have you verified this issue still happens when using the latest snapshot?
You can find snapshot builds here: https://github.com/graalvm/graalvm-ce-dev-builds/releases
Describe the issue
Enso tried to migrate to Truffle 24.2.0, but we are facing starvation when initializing TRegex. This is the stack of the starving thread:
at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:221)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@21/AbstractQueuedSynchronizer.java:754)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(java.base@21/AbstractQueuedSynchronizer.java:1099)
at com.oracle.truffle.api.impl.ThreadLocalHandshake$Barrier.await(ThreadLocalHandshake.java:273)
at com.oracle.truffle.api.impl.ThreadLocalHandshake$Handshake.get(ThreadLocalHandshake.java:500)
at com.oracle.truffle.api.impl.ThreadLocalHandshake$Handshake.get(ThreadLocalHandshake.java:295)
at com.oracle.truffle.polyglot.PolyglotLanguageContext.lambda$ensureInitialized$1(PolyglotLanguageContext.java:862)
at com.oracle.truffle.polyglot.PolyglotLanguageContext$$Lambda/0x00007ae5c80f7670.apply(Unknown Source)
at com.oracle.truffle.api.impl.ThreadLocalHandshake$TruffleSafepointImpl.setBlockedBoundary(ThreadLocalHandshake.java:881)
at com.oracle.truffle.api.impl.ThreadLocalHandshake$TruffleSafepointImpl.setBlocked(ThreadLocalHandshake.java:852)
at com.oracle.truffle.api.TruffleSafepoint.setBlockedThreadInterruptible(TruffleSafepoint.java:338)
at com.oracle.truffle.polyglot.PolyglotLanguageContext.ensureInitialized(PolyglotLanguageContext.java:860)
at com.oracle.truffle.polyglot.PolyglotContextImpl.getContextInitialized(PolyglotContextImpl.java:833)
Code snippet or code repository that reproduces the issue
Author: Jaroslav Tulach <jaroslav.tulach@enso.org>
Date: Tue Mar 25 14:52:15 2025 +0100
Showing starvation problem introduces in Truffle 24.2.0
diff --git pom.xml pom.xml
new file mode 100644
index 0000000..1c471ec
--- /dev/null
+++ pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apidesign.demo</groupId>
+ <artifactId>StarvationOfTruffle</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.release>21</maven.compiler.release>
+ <exec.mainClass>org.apidesign.demo.starvationoftruffle.StarvationOfTruffle</exec.mainClass>
+ <graalvm.version>24.2.0</graalvm.version>
+ <exec.vmArgs>-ea</exec.vmArgs>
+ <exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
+ <exec.appArgs>Hi Hello Hola Hey Ciao Ahoj</exec.appArgs>
+ <exec.mainClass>org.apidesign.demo.starvationoftruffle.StarvationOfTruffle</exec.mainClass>
+ <exec.executable>${java.home}/bin/java</exec.executable>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.graalvm.truffle</groupId>
+ <artifactId>truffle-api</artifactId>
+ <version>${graalvm.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.graalvm.truffle</groupId>
+ <artifactId>truffle-dsl-processor</artifactId>
+ <version>${graalvm.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.graalvm.regex</groupId>
+ <artifactId>regex</artifactId>
+ <version>${graalvm.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>3.5.0</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git src/main/java/org/apidesign/demo/starvationoftruffle/ManyThreadsLanguage.java src/main/java/org/apidesign/demo/starvationoftruffle/ManyThreadsLanguage.java
new file mode 100644
index 0000000..2302a55
--- /dev/null
+++ src/main/java/org/apidesign/demo/starvationoftruffle/ManyThreadsLanguage.java
@@ -0,0 +1,67 @@
+package org.apidesign.demo.starvationoftruffle;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.source.Source;
+import java.util.concurrent.CountDownLatch;
+
+@TruffleLanguage.Registration(id = "many")
+public final class ManyThreadsLanguage extends TruffleLanguage<TruffleLanguage.Env>
+ implements Runnable {
+
+ private static final ContextReference<Env> REF = ContextReference.create(ManyThreadsLanguage.class);
+ private final CountDownLatch all = new CountDownLatch(1);
+ private final Thread[] threads = new Thread[10];
+
+ @Override
+ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
+ return true;
+ }
+
+ @Override
+ protected Env createContext(Env env) {
+ for (var i = 0; i < threads.length; i++) {
+ var t = env.newTruffleThreadBuilder(this).build();
+ t.start();
+ threads[i] = t;
+ }
+ return env;
+ }
+
+ @Override
+ protected CallTarget parse(ParsingRequest request) throws Exception {
+ var orig = request.getSource();
+ var env = REF.get(null);
+ var src = Source.newBuilder("regex", "Flavor=ECMAScript/" + orig.getCharacters() + "/", orig.getName())
+ .mimeType("application/tregex")
+ .internal(true)
+ .build();
+ return env.parseInternal(src);
+ }
+
+
+
+ @Override
+ protected void finalizeContext(Env context) {
+ all.countDown();
+ for (var t : threads) {
+ try {
+ t.join();
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ all.await();
+ return;
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+
+}
diff --git src/main/java/org/apidesign/demo/starvationoftruffle/StarvationOfTruffle.java src/main/java/org/apidesign/demo/starvationoftruffle/StarvationOfTruffle.java
new file mode 100644
index 0000000..05f1f90
--- /dev/null
+++ src/main/java/org/apidesign/demo/starvationoftruffle/StarvationOfTruffle.java
@@ -0,0 +1,18 @@
+package org.apidesign.demo.starvationoftruffle;
+
+import org.graalvm.polyglot.Context;
+
+public class StarvationOfTruffle {
+
+ public static void main(String[] args) {
+ try (var ctx = Context.newBuilder("many", "regex")
+ .allowCreateThread(true)
+ .build()) {
+ var regex = ctx.eval("many", ".*[Hh].*");
+ for (var word : args) {
+ var match = regex.invokeMember("exec", word, 0).getMember("isMatch").asBoolean();
+ System.out.println("word: " + word + " match: " + match);
+ }
+ }
+ }
+}Save the diff into a file X.diff. Then:
$ patch -p0 <X.diffto create pom.xml, ManyThreadsLanguage.java and StarvationOfTruffle.java.
Steps to reproduce the issue
After preparing the sources with patch as described above just:
$ JAVA_HOME=~/bin/graalvm-community-openjdk-21+35.1/ mvn -q clean install exec:exec
the Java process is started, but never finished. Ctrl+\ shows the starvation in PolyglotLanguageContext.ensureInitialized.
Expected behavior
Just run the same with Truffle 24.0.0 and everything works:
$ JAVA_HOME=~/bin/graalvm-community-openjdk-21+35.1/ mvn -q clean install exec:exec -Dgraalvm.version=24.0.0
word: Hi match: true
word: Hello match: true
word: Hola match: true
word: Hey match: true
word: Ciao match: false
word: Ahoj match: true
Additional context
- this problem was discovered while Upgrading to Truffle libraries 24.2.0 enso-org/enso#12500