[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-serviceability-dev
Subject:    Re: RFR JDK-8170089: nsk/jdi/EventSet/resume/resume008: ERROR: suspendCounts don't match for : Commo
From:       "gary.adams () oracle ! com" <gary ! adams () oracle ! com>
Date:       2018-07-25 12:56:40
Message-ID: 8f5e2612-f348-012a-e4d8-9f3c4a082b8d () oracle ! com
[Download RAW message or body]

During some longer testing runs I noticed similar failures for resume002,
resume003 and resume006. I'll spend a few more cycles to see if a more
general purpose solution could be shared across these tests.

On 7/24/18 7:46 PM, Chris Plummer wrote:
> 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 
>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic