RFR JDK-8170089: nsk/jdi/EventSet/resume/resume008: ERROR: suspendCounts don't match for : Common-Cleaner

Chris Plummer chris.plummer at oracle.com
Tue Jul 24 23:46:19 UTC 2018


Hi Gary,

It looks like that should work fine.

thanks,

Chris

On 7/24/18 12:28 PM, Gary Adams wrote:
> 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 



More information about the serviceability-dev mailing list