1 /*
   2  * Copyright (c) 2006, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import com.sun.jdi.*;
  25 import com.sun.jdi.event.*;
  26 import com.sun.jdi.request.*;
  27 
  28 /**
  29  *  @test
  30  *  @bug 6459476
  31  *  @summary Debuggee is blocked,  looks like running
  32  *
  33  *  @author jjh
  34  *
  35  *  @modules jdk.jdi
  36  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  37  *  @run compile -g InterruptHangTest.java
  38  *  @run driver InterruptHangTest
  39  */
  40 
  41 /**
  42  * Debuggee has two threads.  Debugger keeps stepping in
  43  * the first thread.  The second thread keeps interrupting the first
  44  * thread.  If a long time goes by with the debugger not getting
  45  * a step event, the test fails.
  46  */
  47 class InterruptHangTarg {
  48     public static String sync = "sync";
  49     public static void main(String[] args){
  50         int answer = 0;
  51         System.out.println("Howdy!");
  52         Interruptor interruptorThread = new Interruptor(Thread.currentThread());
  53 
  54         synchronized(sync) {
  55             interruptorThread.start();
  56             try {
  57                 sync.wait();
  58             } catch (InterruptedException ee) {
  59                 System.out.println("Debuggee interruptee: interrupted before starting loop");
  60             }
  61         }
  62 
  63         // Debugger will keep stepping thru this loop
  64         for (int ii = 0; ii < 200; ii++) {
  65             answer++;
  66             try {
  67                 // Give other thread a chance to run
  68                 Thread.sleep(100);
  69             } catch (InterruptedException ee) {
  70                 System.out.println("Debuggee interruptee: interrupted at iteration: "
  71                                    + ii);
  72             }
  73         }
  74         // Kill the interrupter thread
  75         interruptorThread.interrupt();
  76         System.out.println("Goodbye from InterruptHangTarg!");
  77     }
  78 }
  79 
  80 class Interruptor extends Thread {
  81     Thread interruptee;
  82     Interruptor(Thread interruptee) {
  83         this.interruptee = interruptee;
  84     }
  85 
  86     public void run() {
  87         synchronized(InterruptHangTarg.sync) {
  88             InterruptHangTarg.sync.notify();
  89         }
  90 
  91         int ii = 0;
  92         while(true) {
  93             ii++;
  94             interruptee.interrupt();
  95             try {
  96                 Thread.sleep(10);
  97             } catch (InterruptedException ee) {
  98                 System.out.println("Debuggee Interruptor: finished after " +
  99                                    ii + " iterrupts");
 100                 break;
 101             }
 102 
 103         }
 104     }
 105 }
 106 
 107     /********** test program **********/
 108 
 109 public class InterruptHangTest extends TestScaffold {
 110     ThreadReference mainThread;
 111     Thread timerThread;
 112     String sync = "sync";
 113     static int nSteps = 0;
 114 
 115     InterruptHangTest (String args[]) {
 116         super(args);
 117     }
 118 
 119     public static void main(String[] args)      throws Exception {
 120         new InterruptHangTest(args).startTests();
 121     }
 122 
 123     /********** event handlers **********/
 124 
 125     public void stepCompleted(StepEvent event) {
 126         synchronized(sync) {
 127             nSteps++;
 128         }
 129         println("Got StepEvent " + nSteps + " at line " +
 130                 event.location().method() + ":" +
 131                 event.location().lineNumber());
 132         if (nSteps == 1) {
 133             timerThread.start();
 134         }
 135     }
 136 
 137     /********** test core **********/
 138 
 139     protected void runTests() throws Exception {
 140         BreakpointEvent bpe = startToMain("InterruptHangTarg");
 141         mainThread = bpe.thread();
 142         EventRequestManager erm = vm().eventRequestManager();
 143 
 144         /*
 145          * Set event requests
 146          */
 147         StepRequest request = erm.createStepRequest(mainThread,
 148                                                     StepRequest.STEP_LINE,
 149                                                     StepRequest.STEP_OVER);
 150         request.enable();
 151 
 152         // Will be started by the step event handler
 153         timerThread = new Thread("test timer") {
 154                 public void run() {
 155                     int mySteps = 0;
 156                     float timeoutFactor = Float.parseFloat(System.getProperty("test.timeout.factor", "1.0"));
 157                     long sleepSeconds = (long)(20 * timeoutFactor);
 158                     println("Timer watching for steps every " + sleepSeconds + " seconds");
 159                     while (true) {
 160                         try {
 161                             Thread.sleep(sleepSeconds * 1000);
 162                             synchronized(sync) {
 163                                 println("steps = " + nSteps);
 164                                 if (mySteps == nSteps) {
 165                                     // no step for a long time
 166                                     failure("failure: Debuggee appears to be hung (no steps for " + sleepSeconds + "s)");
 167                                     vm().exit(-1);
 168                                     break;
 169                                 }
 170                             }
 171                             mySteps = nSteps;
 172                         } catch (InterruptedException ee) {
 173                             break;
 174                         }
 175                     }
 176                 }
 177             };
 178 
 179         /*
 180          * resume the target listening for events
 181          */
 182 
 183         listenUntilVMDisconnect();
 184         timerThread.interrupt();
 185 
 186         /*
 187          * deal with results of test
 188          * if anything has called failure("foo") testFailed will be true
 189          */
 190         if (!testFailed) {
 191             println("InterruptHangTest: passed");
 192         } else {
 193             throw new Exception("InterruptHangTest: failed");
 194         }
 195     }
 196 }