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