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 /** 25 * @test 26 * @bug 6485605 27 * @summary com.sun.jdi.InternalException: Inconsistent suspend policy in internal event handler 28 * 29 * @author jjh 30 * 31 * @modules jdk.jdi 32 * @run build TestScaffold VMConnection TargetListener TargetAdapter 33 * @run compile -g SuspendThreadTest.java 34 * @run driver SuspendThreadTest 35 */ 36 import com.sun.jdi.*; 37 import com.sun.jdi.event.*; 38 import com.sun.jdi.request.*; 39 40 41 /********** target program **********/ 42 43 class SuspendThreadTarg { 44 public static long count; 45 public static boolean active = true; 46 47 public static void bkpt() { 48 count++; 49 } 50 51 public static void main(String[] args){ 52 System.out.println("Howdy!"); 53 54 // We need this to be running so the bkpt 55 // can be hit immediately when it is enabled 56 // in the back-end. 57 while(active) { 58 bkpt(); 59 } 60 System.out.println("Goodbye from SuspendThreadTarg, count = " + count); 61 } 62 } 63 64 /********** test program **********/ 65 66 public class SuspendThreadTest extends TestScaffold { 67 ClassType targetClass; 68 ThreadReference mainThread; 69 70 SuspendThreadTest (String args[]) { 71 super(args); 72 } 73 74 public static void main(String[] args) throws Exception { 75 new SuspendThreadTest(args).startTests(); 76 } 77 78 /********** event handlers **********/ 79 80 // 1000 makes the test take over 2 mins on win32 81 static int maxBkpts = 200; 82 volatile int bkptCount; 83 // to guard against spurious wakeups from bkptSignal.wait() 84 boolean signalSent; 85 // signal that a breakpoint has happened 86 final private Object bkptSignal = new Object() {}; 87 BreakpointRequest bkptRequest; 88 Field debuggeeCountField, debuggeeActiveField; 89 90 // When we get a bkpt we want to disable the request, 91 // resume the debuggee, and then re-enable the request 92 public void breakpointReached(BreakpointEvent event) { 93 System.out.println("Got BreakpointEvent: " + bkptCount + 94 ", debuggeeCount = " + 95 ((LongValue)targetClass. 96 getValue(debuggeeCountField)).value() 97 ); 98 bkptRequest.disable(); 99 } 100 101 public void eventSetComplete(EventSet set) { 102 set.resume(); 103 104 // The main thread watchs the bkptCount to 105 // see if bkpts stop coming in. The 106 // test _should_ fail well before maxBkpts bkpts. 107 synchronized (bkptSignal) { 108 if (bkptCount++ < maxBkpts) { 109 bkptRequest.enable(); 110 } 111 signalSent = true; 112 bkptSignal.notifyAll(); 113 } 114 } 115 116 public void vmDisconnected(VMDisconnectEvent event) { 117 println("Got VMDisconnectEvent"); 118 } 119 120 /********** test core **********/ 121 122 protected void runTests() throws Exception { 123 try { 124 /* 125 * Get to the top of main() 126 * to determine targetClass and mainThread 127 */ 128 BreakpointEvent bpe = startToMain("SuspendThreadTarg"); 129 targetClass = (ClassType)bpe.location().declaringType(); 130 mainThread = bpe.thread(); 131 EventRequestManager erm = vm().eventRequestManager(); 132 133 Location loc1 = findMethod(targetClass, "bkpt", "()V").location(); 134 135 bkptRequest = erm.createBreakpointRequest(loc1); 136 137 // Without this, it is a SUSPEND_ALL bkpt and the test will pass 138 bkptRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); 139 bkptRequest.enable(); 140 141 debuggeeCountField = targetClass.fieldByName("count"); 142 debuggeeActiveField = targetClass.fieldByName("active"); 143 try { 144 addListener (this); 145 } catch (Exception ex){ 146 ex.printStackTrace(); 147 failure("failure: Could not add listener"); 148 throw new Exception("SuspendThreadTest: failed", ex); 149 } 150 151 int prevBkptCount; 152 vm().resume(); 153 synchronized (bkptSignal) { 154 while (bkptCount < maxBkpts) { 155 prevBkptCount = bkptCount; 156 // If we don't get a bkpt within 5 secs, 157 // the test fails 158 signalSent = false; 159 do { 160 try { 161 bkptSignal.wait(5000); 162 } catch (InterruptedException ee) { 163 } 164 } while (signalSent == false); 165 if (prevBkptCount == bkptCount) { 166 failure("failure: test hung"); 167 break; 168 } 169 } 170 } 171 println("done with loop"); 172 bkptRequest.disable(); 173 removeListener(this); 174 175 /* 176 * deal with results of test 177 * if anything has called failure("foo") testFailed will be true 178 */ 179 if (!testFailed) { 180 println("SuspendThreadTest: passed"); 181 } else { 182 throw new Exception("SuspendThreadTest: failed"); 183 } 184 } finally { 185 if (targetClass != null && debuggeeActiveField != null) { 186 targetClass.setValue(debuggeeActiveField, vm().mirrorOf(false)); 187 } 188 } 189 } 190 }