The DebuggerThreadTest ensures it is in sync
at the beginning of RunTests with a breakpoint event
in DebuggerThreadTarg ready() method.

The DebuggerThreadTest then continues with
dumpThreads() and listenUntilVMDisconnect()
completes.

If the DebugThreadTarg is resumed prematurely,
the main thread in the debuggee could complete
before the dumpThreads enumeration is complete.

DebuggerThreadTest
  main()
    startTests()
       runTests()
          startTo( "DebuggerThreadTarg.ready()")
          dumpThreads()
          listenUntilVMDisconnect()

DebuggerThreadTarg
  main()
     ready()

Revised fix:
  - Prevents the NPE from a finished thread group
  - Fails the test with a message indicating
     number of premature completed threads.

diff --git a/test/jdk/com/sun/jdi/DebuggerThreadTest.java b/test/jdk/com/sun/jdi/DebuggerThreadTest.java
--- a/test/jdk/com/sun/jdi/DebuggerThreadTest.java
+++ b/test/jdk/com/sun/jdi/DebuggerThreadTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, 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
@@ -76,8 +76,16 @@
         Thread list[] = new Thread[listThreads * 2];
         int gotThreads = tg.enumerate(list, true);
         for (int i = 0; i < Math.min(gotThreads, list.length); i++){
+            int finishedThreads = 0;
             Thread t = list[i];
-            String groupName = t.getThreadGroup().getName();
+            ThreadGroup tga = t.getThreadGroup();
+            String groupName;
+            if (tga == null) {
+                groupName = "<completed>";
+                finishedThreads++ ;
+            } else {
+                groupName =tga.getName();
+            }

             System.out.println("Thread [" + i + "] group = '" +
                                groupName +
@@ -89,7 +97,10 @@
                 failure("FAIL: non-daemon thread '" + t.getName() +
                         "' found in ThreadGroup '" + groupName + "'");
             }
-
+            if (finishedThreads > 0 ) {
+                failure("FAIL: " + finishedThreads +
+                        " threads completed while VM suspended.");
+            }
         }
     }


On 9/4/18, 3:15 PM, Chris Plummer wrote:
Hi Gary,

The failed case only had:

Thread [0] group = 'system' name = 'Reference Handler' daemon = true
Thread [1] group = 'system' name = 'Finalizer' daemon = true
Thread [2] group = 'system' name = 'Signal Dispatcher' daemon = true
Thread [3] group = 'system' name = 'process reaper' daemon = true

That would indicate that 'main' is likely the thread that exited. Seems odd. Isn't that the thread that the test is executing in?

If you can't reproduce it, maybe it would be better to commit a diagnostic fix like the one I suggested and keep an eye on it. However, it only seems to have failed once due to this reason, so unless it is a new problem we may never see it again.

Chris

On 9/4/18 11:28 AM, Gary Adams wrote:
I haven't been able to reproduce the problem locally.
Trying larger test runs on mach5 now.

Here's the output from a successful test run.
If any of the threads exited, they would have a null group name.

Howdy!
Thread [0] group = 'system' name = 'Reference Handler' daemon = true
Thread [1] group = 'system' name = 'Finalizer' daemon = true
Thread [2] group = 'system' name = 'Signal Dispatcher' daemon = true
Thread [3] group = 'system' name = 'process reaper' daemon = true
Thread [4] group = 'main' name = 'main' daemon = false
Thread [5] group = 'main' name = 'pool-1-thread-1' daemon = true
Thread [6] group = 'AgentVMThreadGroup' name = 'AgentVMThread' daemon = false Thread [7] group = 'AgentVMThreadGroup' name = 'output reader' daemon = false Thread [8] group = 'AgentVMThreadGroup' name = 'output reader' daemon = false
Thread [9] group = 'AgentVMThreadGroup' name = 'Thread-5' daemon = true
Thread [10] group = 'InnocuousThreadGroup' name = 'Common-Cleaner' daemon = true Thread [11] group = 'JDI [1485331767]' name = 'JDI Internal Event Handler' daemon = true Thread [12] group = 'JDI [1485331767]' name = 'JDI Target VM Interface' daemon = true
Goodbye from DebuggerThreadTarg!


On 9/4/18, 2:16 PM, Chris Plummer wrote:
Can you reproduce the problem? If so, maybe to find out which thread is a problem you could check for null, print the thread info, and then fail the test.

Chris

On 9/4/18 11:14 AM, Gary Adams wrote:
I'm not sure which thread exited causes the NPE.
This patch will let  the test continue and at least
let the list of threads be processed.

The test walks up the parents to the initial thread
and then "enumerates()" the set of the threads to check.
There is an inherent race condition in enumerate()
that recognizes it is a snapshot of a moving target.

On 9/4/18, 1:51 PM, Chris Plummer wrote:
Hi Gary,

Why has the thread exited if the debuggee is still running?

Chris

On 9/4/18 5:22 AM, Gary Adams wrote:
Here's a quick fix to avoid the NPE using a getThreadGroup() which could be null
if the thread has terminated.

  Issue: https://bugs.openjdk.java.net/browse/JDK-8210252

diff --git a/test/jdk/com/sun/jdi/DebuggerThreadTest.java b/test/jdk/com/sun/jdi/DebuggerThreadTest.java
--- a/test/jdk/com/sun/jdi/DebuggerThreadTest.java
+++ b/test/jdk/com/sun/jdi/DebuggerThreadTest.java
@@ -77,7 +77,8 @@
         int gotThreads = tg.enumerate(list, true);
for (int i = 0; i < Math.min(gotThreads, list.length); i++){
             Thread t = list[i];
- String groupName = t.getThreadGroup().getName();
+ ThreadGroup tga = t.getThreadGroup();
+ String groupName = (tga == null ? "<completed>": tga.getName());

             System.out.println("Thread [" + i + "] group = '" +
groupName +









Reply via email to