jdk/test/com/sun/jdi/TwoThreadsTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /**
       
    25  *  @test
       
    26  *  @bug 6296125
       
    27  *  @summary  JDI: Disabling an EventRequest can cause a multi-threaded debuggee to hang
       
    28  *
       
    29  *  @author jjh
       
    30  *
       
    31  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
       
    32  *  @run compile -g TwoThreadsTest.java
       
    33  *  @run main TwoThreadsTest
       
    34  */
       
    35 import com.sun.jdi.*;
       
    36 import com.sun.jdi.event.*;
       
    37 import com.sun.jdi.request.*;
       
    38 
       
    39 import java.util.*;
       
    40 
       
    41 /*
       
    42  * This debuggee basically runs two threads each of
       
    43  * which loop, hitting a bkpt in each iteration.
       
    44  *
       
    45  */
       
    46 class TwoThreadsTarg extends Thread {
       
    47     static boolean one = false;
       
    48     static String name1 = "Thread 1";
       
    49     static String name2 = "Thread 2";
       
    50     static int count = 100;
       
    51 
       
    52     public static void main(String[] args) {
       
    53         System.out.println("Howdy!");
       
    54         TwoThreadsTarg t1 = new TwoThreadsTarg(name1);
       
    55         TwoThreadsTarg t2 = new TwoThreadsTarg(name2);
       
    56 
       
    57         t1.start();
       
    58         t2.start();
       
    59     }
       
    60 
       
    61     public TwoThreadsTarg(String name) {
       
    62         super(name);
       
    63     }
       
    64 
       
    65     public void run() {
       
    66         if (getName().equals(name1)) {
       
    67             run1();
       
    68         } else {
       
    69             run2();
       
    70         }
       
    71     }
       
    72 
       
    73     public void bkpt1(int i) {
       
    74         yield();
       
    75     }
       
    76 
       
    77     public void run1() {
       
    78         int i = 0;
       
    79         while (i < count) {
       
    80             i++;
       
    81             bkpt1(i);
       
    82         }
       
    83     }
       
    84 
       
    85     public void bkpt2(int i) {
       
    86         yield();
       
    87     }
       
    88 
       
    89     public void run2() {
       
    90         int i = 0;
       
    91         while (i < count) {
       
    92             i++;
       
    93             bkpt2(i);
       
    94         }
       
    95     }
       
    96 }
       
    97 
       
    98 /********** test program **********/
       
    99 
       
   100 public class TwoThreadsTest extends TestScaffold {
       
   101     ReferenceType targetClass;
       
   102     ThreadReference mainThread;
       
   103     BreakpointRequest request1;
       
   104     BreakpointRequest request2;
       
   105     static volatile int bkpts = 0;
       
   106     Thread timerThread;
       
   107     static int waitTime = 20000;
       
   108 
       
   109     TwoThreadsTest (String args[]) {
       
   110         super(args);
       
   111     }
       
   112 
       
   113     public static void main(String[] args)      throws Exception {
       
   114         new TwoThreadsTest(args).startTests();
       
   115     }
       
   116 
       
   117     /* BreakpointEvent handler */
       
   118 
       
   119     public void breakpointReached(BreakpointEvent event) {
       
   120         if (bkpts == 0) {
       
   121             /*
       
   122              * This thread will watch for n secs to go by with no
       
   123              * calls to this method.
       
   124              */
       
   125             timerThread.start();
       
   126         }
       
   127 
       
   128         synchronized("abc") {
       
   129             /*
       
   130              * Note that this will most likely never get to
       
   131              * the number of times the two bkpt lines in the debuggee
       
   132              * are hit because bkpts are lost while they are disabled.
       
   133              */
       
   134             bkpts++;
       
   135         }
       
   136 
       
   137         /*
       
   138          * The bug occurs when the requests are disabled
       
   139          * and then re-enabled during the event handler.
       
   140          */
       
   141         request1.disable();
       
   142         request2.disable();
       
   143 
       
   144         /*
       
   145          * This code between the disables and enables
       
   146          * is just filler that leaves the requests disabled
       
   147          * for awhile.  I suppose a sleep could be used instead
       
   148          */
       
   149         Method mmm = event.location().method();
       
   150         List lvlist;
       
   151         try {
       
   152             lvlist = mmm.variablesByName("i");
       
   153         } catch (AbsentInformationException ee) {
       
   154             failure("FAILED: can't get local var i");
       
   155             return;
       
   156         }
       
   157         LocalVariable ivar = (LocalVariable)lvlist.get(0);
       
   158 
       
   159         ThreadReference thr = event.thread();
       
   160         StackFrame sf;
       
   161         try {
       
   162             sf = thr.frame(0);
       
   163         } catch (IncompatibleThreadStateException ee) {
       
   164             failure("FAILED: bad thread state");
       
   165             return;
       
   166         }
       
   167         Value ival = sf.getValue(ivar);
       
   168         println("Got bkpt at: " + event.location() + ", i = " + ival);
       
   169         request1.enable();
       
   170         request2.enable();
       
   171 
       
   172     }
       
   173 
       
   174     /********** test core **********/
       
   175 
       
   176     protected void runTests() throws Exception {
       
   177 
       
   178         /*
       
   179          * Get to the top of main()
       
   180          * to determine targetClass and mainThread
       
   181          */
       
   182         BreakpointEvent bpe = startToMain("TwoThreadsTarg");
       
   183         targetClass = bpe.location().declaringType();
       
   184         mainThread = bpe.thread();
       
   185         EventRequestManager erm = vm().eventRequestManager();
       
   186         final Thread mainThread = Thread.currentThread();
       
   187 
       
   188         /*
       
   189          * Set event requests
       
   190          */
       
   191         Location loc1 = findMethod(targetClass, "bkpt1", "(I)V").location();
       
   192         Location loc2 = findMethod(targetClass, "bkpt2", "(I)V").location();
       
   193         request1 = erm.createBreakpointRequest(loc1);
       
   194         request2 = erm.createBreakpointRequest(loc2);
       
   195         request1.enable();
       
   196         request2.enable();
       
   197 
       
   198         /*
       
   199          * This thread will be started when we get the first bkpt.
       
   200          * (Which we always expect to get).
       
   201          * It awakens every n seconds and checks to see if we
       
   202          * got any breakpoint events while it was asleep.
       
   203          */
       
   204         timerThread = new Thread("test timer") {
       
   205                 public void run() {
       
   206                     int myBkpts = bkpts;
       
   207                     while (true) {
       
   208                         try {
       
   209                             Thread.sleep(waitTime);
       
   210                             System.out.println("bkpts = " + bkpts);
       
   211                             if (myBkpts == bkpts) {
       
   212                                 // no bkpt for 'waitTime' secs
       
   213                                 failure("failure: Debuggee appears to be hung");
       
   214                                 vmDisconnected = true;
       
   215                                 // This awakens the main thread which is
       
   216                                 // waiting for a VMDisconnect.
       
   217                                 mainThread.interrupt();
       
   218                                 break;
       
   219                             }
       
   220                             myBkpts = bkpts;
       
   221                         } catch (InterruptedException ee) {
       
   222                             // If the test completes, this occurs.
       
   223                             println("timer Interrupted");
       
   224                             break;
       
   225                         }
       
   226                     }
       
   227                 }
       
   228             };
       
   229 
       
   230         /*
       
   231          * resume the target, listening for events
       
   232          */
       
   233         listenUntilVMDisconnect();
       
   234         timerThread.interrupt();
       
   235         /*
       
   236          * deal with results of test
       
   237          * if anything has called failure("foo") testFailed will be true
       
   238          */
       
   239         if (!testFailed) {
       
   240             println("TwoThreadsTest: passed; bkpts = " + bkpts);
       
   241         } else {
       
   242             throw new Exception("TwoThreadsTest: failed; bkpts = " + bkpts);
       
   243         }
       
   244     }
       
   245 }