Hi Gary,

I've been having trouble following the control flow of this test. One thing I've stumbled across is the following:

            /* A debuggee class must define 'methodForCommunication'
             * method and invoke it in points of synchronization
             * with a debugger.
             */
setCommunicationBreakpoint(debuggeeClass,"methodForCommunication");

So why isn't this mode of synchronization good enough? Is it because it was not designed with the understanding that the debugger might be doing suspended thread counts, and suspending all threads at the breakpoint messes up the test?

From what I can tell of the test, after the debuggee is started and hits the default breakpoint at the start of main(), the debugger then does a vm.resume() at the start of the for loop in the runTest() method. The debuggee then creates a thread and calls methodForCommunication(). There is already a breakpoint set there by the above debuggee code. It's unclear to me what happens as a result of this breakpoint and how it serves the test. Also unclear to me who is responsible for the vm.resume() after the breakpoint is hit.

The debugger then requests all ThreadStart events, requesting that no threads be disabled when it is sent. I think you are saying that when the ThreadStart event comes in, sometimes we are at the methodForCommunication breakpoint, with all threads disabled, and this messes up the thread suspend counts. You want to delay 100ms so the breakpoint event can be processed and threads resumed again (although I can't see who actually resumes the thread after hitting the methodForCommunication breakpoint).

Chris

On 7/17/18 8:33 AM, Gary Adams wrote:
A race condition exists between the debugger and the debuggee.

The first test thread is started with SUSPEND_NONE policy set.
While processing the thread start event the debugger captures
an initial set of thread suspend counts and resumes the
debuggee vm. If the debuggee advances quickly it reaches
the breakpoint set for methodForCommunication. Since the breakpoint
carries with it SUSPEND_ALL policy, when the debugger captures a second
set of suspend counts, it will not match the expected counts for
a SUSPEND_NONE scenario.

The proposed fix introduces a yield in the debuggee test thread run method
to allow the debugger to get the expected sampled values.

  Issue: https://bugs.openjdk.java.net/browse/JDK-8170089
  Webrev: http://cr.openjdk.java.net/~gadams/8170089/webrev.00/


test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestDebuggerType1.java:
...
   186        private void setCommunicationBreakpoint(ReferenceType refType, String methodName) {    187            Method method = debuggee.methodByName(refType, methodName);
   188            Location location = null;
   189            try {
   190                location = method.allLineLocations().get(0);
   191            } catch (AbsentInformationException e) {
   192                throw new Failure(e);
   193            }
   194            bpRequest = debuggee.makeBreakpoint(location);
   195

   196 bpRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);

   197            bpRequest.putProperty("number", "zero");
   198            bpRequest.enable();
   199
   200            eventHandler.addListener(
   201                 new EventHandler.EventListener() {
   202                     public boolean eventReceived(Event event) {
   203                        if (event instanceof BreakpointEvent && bpRequest.equals(event.request())) {
   204                            synchronized(eventHandler) {
   205                                display("Received communication breakpoint event.");
   206                                bpCount++;
   207                                eventHandler.notifyAll();
   208                            }
   209                            return true;
   210                        }
   211                        return false;
   212                     }
   213                 }
   214            );
   215        }


test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java:
...
   140                    display("......--> vm.suspend();");
   141                    vm.suspend();
   142
   143                    display("        getting : Map<String, Integer> suspendsCounts1");
   144
   145                    Map<String, Integer> suspendsCounts1 = new HashMap<String, Integer>();    146                    for (ThreadReference threadReference : vm.allThreads()) {    147 suspendsCounts1.put(threadReference.name(), threadReference.suspendCount());
   148                    }
   149                    display(suspendsCounts1.toString());
   150
   151                    display("        eventSet.resume;");
   152                    eventSet.resume();
   153
   154                    display("        getting : Map<String, Integer> suspendsCounts2");

This is where the breakpoint is encountered before the second set of suspend counts is acquired.

   155                    Map<String, Integer> suspendsCounts2 = new HashMap<String, Integer>();    156                    for (ThreadReference threadReference : vm.allThreads()) {    157 suspendsCounts2.put(threadReference.name(), threadReference.suspendCount());
   158                    }
   159                    display(suspendsCounts2.toString());


Reply via email to