Here's a quick prototype to add a variable to the debuggee.
The debugger sets it at the end of each completed test case.
The debuggee can then check for the value change to delay
hitting the breakpoint which interfered with suspend count checks.
Would need to add a bit more error and timeout checking to
complete the fix. Should also check if the other resume008 test cases
need similar synchronization. Could possibly migrate the code up to
TestDebuggerType1 if other tests also needed this generic capability.
diff --git
a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java
b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java
---
a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java
+++
b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java
@@ -63,6 +63,9 @@
* to be resulting in the event.
* - Upon getting new event, the debugger
* performs the check corresponding to the event.
+ * - The debugger informs the debuggee when it completes
+ * each test case, so it will wait before hitting
+ * communication breakpoints.
*/
public class resume008 extends TestDebuggerType1 {
@@ -234,6 +237,7 @@
default: throw new Failure("** default case 1
**");
}
+ informDebuggeeTestCase(i);
}
display("......--> vm.resume()");
@@ -255,4 +259,25 @@
}
}
+ /**
+ * Inform debuggee which thread test the debugger has completed.
+ * Used for synchronization, so the debuggee does not move too
quickly.
+ * @param testCase index of just completed test
+ */
+ void informDebuggeeTestCase(int testCase) {
+ if (!EventHandler.isDisconnected() && debuggeeClass != null) {
+ try {
+ ((ClassType)debuggeeClass)
+ .setValue(debuggeeClass.fieldByName("testCase"),
+ vm.mirrorOf(testCase));
+ } catch (InvalidTypeException ite) {
+ // ignored
+ } catch (ClassNotLoadedException cnle) {
+ // ignored
+ } catch (VMDisconnectedException e) {
+ // ignored
}
+ }
+ }
+
+}
diff --git
a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java
b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java
---
a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java
+++
b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java
@@ -62,6 +62,7 @@
static int exitCode = PASSED;
+ static int testCase = -1;
static int instruction = 1;
static int end = 0;
// static int quit = 0;
@@ -104,6 +105,15 @@
threadStart(thread0);
thread1 = new Threadresume008a("thread1");
+ // Wait for debugger to complete the
first test case
+ // before advancing to the next breakpoint
+ while (testCase < 0) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // ignored
+ }
+ }
methodForCommunication();
break;
On 7/20/18, 2:37 PM, Chris Plummer wrote:
Hi Gary,
The test fails if the breakpoint event comes in after the test
captures the initial thread suspend counts and before the test
captures the 2nd suspend counts.
debugger> getting : Map<String, Integer> suspendsCounts1
debugger> {Reference Handler=1, Common-Cleaner=1, main=1, Signal
Dispatcher=1, Finalizer=1}
debugger> eventSet.resume;
debugger> getting : Map<String, Integer> suspendsCounts2
EventHandler> Received event set with policy = SUSPEND_ALL
EventHandler> Event: BreakpointEventImpl req breakpoint request
nsk.jdi.EventSet.resume.resume008a:60 (enabled)
debugger> Received communication breakpoint event.
debugger> {Reference Handler=2, Common-Cleaner=2, main=1, Signal
Dispatcher=2, Finalizer=2}
So we end up with some threads starting with 1 suspend and ending
with 2 (not clear to me why main is still at 1).
It will pass if the breakpoint comes in after it does both of
suspend count checks, as you have shown with the sleep(100)
solution. Output looks like this:
debugger> got new ThreadStartEvent with propety 'number' ==
ThreadStartRequest1
...
debugger> ......--> vm.suspend();
debugger> getting : Map<String, Integer> suspendsCounts1
debugger> {Reference Handler=1, thread0=1, Common-Cleaner=1, main=1,
Signal Dispatcher=1, Finalizer=1}
debugger> eventSet.resume;
debugger> getting : Map<String, Integer> suspendsCounts2
debugger> {Reference Handler=1, thread0=1, Common-Cleaner=1, main=1,
Signal Dispatcher=1, Finalizer=1}
...
debugger> Received communication breakpoint event.
I've also shown that it passes if the breakpoint always comes in
before capturing the initial suspend counts. I added a sleep on the
debugger side right after eventHandler.waitForRequestedEventSet()
returns. Output looks like:
debugger> Received communication breakpoint event.
debugger> got new ThreadStartEvent with propety 'number' ==
ThreadStartRequest1
...
debugger> ......--> vm.suspend();
debugger> getting : Map<String, Integer> suspendsCounts1
debugger> {Reference Handler=2, thread0=2, Common-Cleaner=2, main=2,
Signal Dispatcher=2, Finalizer=2}
debugger> eventSet.resume;
debugger> getting : Map<String, Integer> suspendsCounts2
debugger> {Reference Handler=2, thread0=2, Common-Cleaner=2, main=2,
Signal Dispatcher=2, Finalizer=2}
I think we should add synchronization to force one of these two
outcomes. For the first, you would need to make the debugger modify
some variable that the debuggee is watching (sitting in a loop
waiting for it to change). For the second, you can rely on the
existing methodForCommunication() approach. You just need to
restructure the debugger a bit. I had started down this path late
Wednesday, but got sidetracked by a few other things. I can look
into it some more if you'd like.
thanks,
Chris