eclipse-jdt / eclipse.jdt.debug

Eclipse Public License 2.0
16 stars 45 forks source link

Debug "step" and "resume" operations are grayed out with breakpoints in virtual threads #345

Open minduch opened 9 months ago

minduch commented 9 months ago

Eclipse 2023-12 M2, Java Temurin 21.0.1. Microsoft Windows [Version 10.0.23580.1000]

Launching debug of a Java Application project (uses Virtual Threads in case it matters) hits a breakpoint during its startup (after running a couple of seconds) the breakpoint System.out.println("HERE!"); is encountered. Code is compiled for Java 17.

image

The debug operations "step" (into/over/return) and "resume" are grayed out and cannot be performed. Also note the tree view having two empty lines. It doesn't matter which thread I select in the Debug view, the operations in question are always disabled:

image

This problem can be reproduced all the time.

iloveeclipse commented 9 months ago

1) Is this a regression, and if yes, which version works? 2) Any chance to provide steps to reproduce / example project?

minduch commented 9 months ago

Worse in 2023-09 GA (+ Java 21 support added):

image

However, with Java Temurin - Eclipse Adoptium 17.0.9+9 - it works fine in both IDE's. So it must be Java 17/21 related, here 2023-09 GA:

image

and also works in 2023-12 M2:

image

Must I try to find a sample project, I don't have many of those?

iloveeclipse commented 9 months ago

I'm lost. Ist this virtual threads related, how it can work on Java 17 which does not have virtual threads? Is this not related to virtual threads, what is the key difference in what you are doing & the rest of the world with working debugger?

Please try to isolate the root cause of your problem. IDE update, Java update, specific code you have or whatever else.

Once you have that, try to provide steps to reproduce for us so we can fix the problem, whatever it is.

minduch commented 9 months ago

I think it's Java 21-related, or to be more sure, post-Java 17 specific. Virtual Threads were implemented from Java 19 and better, and we have preview support for it, but it's disabled. So the code being used targets Java 21 (only for the Virtual Threads part).

It's not IDE. It's Java 21. Using Java 20 (OpenJDK 64-Bit Server VM Temurin-20.0.2+9 (build 20.0.2+9, mixed mode, sharing)) and "--enable-preview" (VirtualThreads are used), the break-point enables the debug operations (step/resume), but has a problem in the Debug view (one thread missing that is sitting on the same breakpoint too, but in another thread):

image

When stepping and debugging code, the Debug view thread that is "missing":

image

Turning off "--enable-preview" in Java 20 makes it work:

image

We have a command line option to disable Virtual Threads, so this problem seems to become clear now. The Debug view with Virtual Threads has a problem when it hits breakpoints in one or more threads. This is using Java 21 without "--enable-preview" and our VirtualThreads turned OFF:

image

The interesting thing is that we only have one breakpoint at a time when VirtualThreads are off. So I guess somebody with more experience in this area should look at the problem (as it involves two "probably" Virtual Threads being break-point'ed, but I'm not sure).

minduch commented 9 months ago

@iloveeclipse Yep, I thinks this is an accurate description from the tests I have performed.

iloveeclipse commented 9 months ago

OK, could you please try to isolate some simple example that would allow us to reproduce the issue? Or, if the application is available, provide steps to reproduce?

If this is caused by virtual threads, I assume one precondition is a breakpoint in code executed by a virtual thread. Most likely you have multiple virtual threads running in one "real" thread and hitting same breakpoint one after each other, and debugger confused by that (because it would be same real thread)?

iloveeclipse commented 9 months ago

I wonder if you can change the breakpoint to print current thread name, what you would see on console? Also assuming there are multiple hits on same breakpoint, could you set hit count to one, just to see if debugger would "work" again? Unfortunately I have not much time to play with that, but I guess you could try to compose simple example with virtual threads hitting same breakpoint again and again. If you could do that & it will reproduce the issue, it would help a lot.

minduch commented 9 months ago

Well, that was not much help. If I use System.err, it will probably sync the threads somehow so then I don't get the problem at all. I however changed the code a bit instead of System.err.println("HERE!"); to

      ByteArrayOutputStream out=new ByteArrayOutputStream();
      try(PrintStream ps=new PrintStream(out))
        {
        new Exception("StackTrace").printStackTrace(ps);
        }
      System.err.println("HERE: "+new String(out.toByteArray()));

And set the break-point on the System.err line, and now THAT thread is OK in Debug view (display + enabled step/resume operations), and the other thread is NOT: image Above, I highlighted the other thread not shown in the Debug view, so the step/resume operations are disabled.

I'm not becoming less confused releasing all threads and looking at the printed stack traces, they all come from the same thread as it looks like, and there is no point in sharing this info here - it's just a plain stacktrace from the two System.err calls, all originating from lThread[#48,stderr]/runnable@ForkJoinPool-1-worker-2 HERE: java.lang.Exception: StackTrace, the name lThread indicates it's a Virtual Thread I think.

--> Forget the paragraph above, the lThread that is shown is the our stderr reader virtual thread, this is the thread actually being executed: HERE: thread = Thread[#60,iiziServer,10,main] - thread group = java.lang.ThreadGroup[name=main,maxpri=10] when I changed the code to

      {
      System.err.println("HERE: thread = "+Thread.currentThread()+" - thread group = "+Thread.currentThread().getThreadGroup());
      }

and that is a Platform Thread.

fdummert commented 5 months ago

We're having a multi-threaded app based on virtual threads. We're currently using Eclipse 20231201-2043 with jdt debug 3.21.200.v20231103-0755. The described behavior happens indeed when there are two suspended virtual threads. For me, it displays fine for a moment, but then after a moment one suspended thread disappears from the debug view, leaving blank lines: Screenshot_20240229_102320 But the most annoying issue is, even with only one virtual thread on a breakpoint, that after <10s, with or without any action like stepping, expanding variables, ... the debug view collapses, variable view gets closed, stepping is disabled, and we have again to open the suspended thread, see screencast: https://github.com/eclipse-jdt/eclipse.jdt.debug/assets/3638091/b6426f63-cff2-446a-b429-8d136a9f7201 Sometimes the suspended virtual thread is even not shown at all: Screenshot_20240229_102342 That makes debugging virtual threads really painful. I'm not sure if this is easily reproducible with a toy app, but this is happening in many different apps we have, all based on virtual threads. Maybe for a reproducer you need to setup a simple web server app based on virtual threads (for example Jetty with workers based on virtual threads) and try to debug incoming requests to your test app.

iloveeclipse commented 2 months ago

@fdummert, @minduch : if you would provide a simple self containing example project it would increase a chance for this bug to be addressed at some time.

fdummert commented 2 months ago

Hi @iloveeclipse, please use https://github.com/fdummert/EclipseVThreads.git as an example project that demonstrates the faulty behaviors. All three debugging blockers can be seen there: collapse of the debug view, vanishing of the suspended thread in the debug view, display of an empty line instead of the suspended thread in the debug view. A few details on how to debug are described in the readme file.