oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.39k stars 1.64k forks source link

Graalvm 20.2.0 Deadlock in chromeinspector.server.CommandProcessThread when debugging #2865

Closed Caffeine-01 closed 3 years ago

Caffeine-01 commented 4 years ago

Found one Java-level deadlock:

"ajp-nio-0.0.0.0-8009-exec-21": waiting for ownable synchronizer 0x0000000572418480, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync), which is held by "chromeinspector.server.CommandProcessThread" "chromeinspector.server.CommandProcessThread": waiting for ownable synchronizer 0x00000001c5e235f8, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "ajp-nio-0.0.0.0-8009-exec-106" "ajp-nio-0.0.0.0-8009-exec-106": waiting for ownable synchronizer 0x0000000572418480, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync), which is held by "chromeinspector.server.CommandProcessThread"

Java stack information for the threads listed above:

"ajp-nio-0.0.0.0-8009-exec-21": at jdk.internal.misc.Unsafe.park(java.base@11.0.8/Native Method)

"chromeinspector.server.CommandProcessThread": at jdk.internal.misc.Unsafe.park(java.base@11.0.8/Native Method)

"ajp-nio-0.0.0.0-8009-exec-106": at jdk.internal.misc.Unsafe.park(java.base@11.0.8/Native Method)

oubidar-Abderrahim commented 4 years ago

Hi, could you provide a small reproducer for this deadlock?

Caffeine-01 commented 4 years ago

It's a race condition and the initial deadlock stacktracess were user triggered. It took me a while to reproduce it easily. Eventually the code below deadlocked, It's not exactly the same deadlock. i.e This one is on breakpoint.dispose() the previous was on debugSession.install()

package graalvmDeadlock;

import com.oracle.truffle.api.debug.Breakpoint;
import com.oracle.truffle.api.debug.Debugger;
import java.io.IOException;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.Source;

public class Main {

   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) throws Exception {
      for (;;) {
         var engine = Engine.newBuilder().build();
         var code = "let i = 0;\n"
                + "for(;;){\n"
                + "  i++;\n"
                + "}";

         new Thread(
            () -> {
               try {
                  var source = Source.newBuilder("js", code, "LoopTest").build();
                  Context.newBuilder("js").engine(engine).build().eval(source);
               } catch (IOException ex) {
                  throw new RuntimeException(ex);
               }
            },
            "JsLoop"
         ).start();

         var breakPointThread = new Thread(
               () -> {
                  try (
                     var session = Debugger.find(engine).startSession(event -> {
                     event.prepareStepInto(1);
                  })) {
                     var source = com.oracle.truffle.api.source.Source.newBuilder("js", code, "LoopTest").build();                  
                     for(;;) {
                        var breakPoint = Breakpoint.newBuilder(source)
                              .lineIs(3)
                              .resolveListener((breakpoint, section) -> {
                                 System.out.println(breakpoint + " " + section);
                              })
                              .build();
                        try {
                           Thread.sleep(9);
                        } catch (InterruptedException ex) {
                           return;
                        }
                        System.out.println("Install breakpoint");
                        session.install(breakPoint);
                        breakPoint.dispose();
                     }
                  }
               },
               "Debugger"
         );

         breakPointThread.start();         
         Thread.sleep(10);
         System.out.println("Engine close");
         engine.close(true);
         breakPointThread.interrupt();
      }

   }

}

Found one Java-level deadlock:

"main": waiting for ownable synchronizer 0x00000005e89983d8, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "JsLoop" "JsLoop": waiting to lock monitor 0x00007fb20c007380 (object 0x00000005e88f7248, a com.oracle.truffle.api.debug.Breakpoint), which is held by "Debugger" "Debugger": waiting for ownable synchronizer 0x00000005e89983d8, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "JsLoop"

Java stack information for the threads listed above:

"main": at jdk.internal.misc.Unsafe.park(java.base@11.0.8/Native Method)

Found 1 deadlock.

oubidar-Abderrahim commented 4 years ago

An Internal ticket was created for the Dev team to investigate and fix this issue

gilles-duboscq commented 3 years ago

@entlicher, it this one of the instrumentation deadlock that was fixed recently? Is this resolved by d37946aec3112a015b3f205545cf993c3d0c31c2? If that is the case then this is fixed in 20.3.0

fernando-valdez commented 3 years ago

@Caffeine-01 can you please test this issue using the latest GraalVM version, and share your results?

oubidar-Abderrahim commented 3 years ago

Closed as resolved