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