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 6417044 27 * @summary Test deadlock in MBeanRegistration.postRegister method 28 * @author Eamonn McManus, Daniel Fuchs 29 * 30 * @run clean PostRegisterDeadlockTest 31 * @run build PostRegisterDeadlockTest 32 * @run main PostRegisterDeadlockTest 33 */ 34 35import java.lang.Thread.State; 36import java.util.concurrent.*; 37import javax.management.*; 38 39public class PostRegisterDeadlockTest { 40 public static interface BlibbyMBean {} 41 42 public static class Blibby implements BlibbyMBean, MBeanRegistration { 43 public Blibby(MBeanServer mbs, ObjectName otherName) { 44 this.mbs = mbs; 45 this.otherName = otherName; 46 } 47 48 public ObjectName preRegister(MBeanServer mbs, ObjectName on) { 49 return on; 50 } 51 52 public void preDeregister() {} 53 54 public void postRegister(Boolean done) { 55 // If no other MBean was registered 56 // do nothing. 57 // 58 if (otherName == null) return; 59 60 // Check that we can unregister 61 // other MBean 62 try { 63 Thread t = new Thread() { 64 public void run() { 65 try { 66 try { 67 mbs.unregisterMBean(otherName); 68 } catch (InstanceNotFoundException x) { 69 // Race condition! 70 System.out.println(otherName+ 71 " was unregistered by main thread."); 72 } 73 } catch (Throwable e) { 74 e.printStackTrace(System.out); 75 fail(e.toString()); 76 } 77 } 78 }; 79 t.start(); 80 t.join(5000L); 81 if (t.isAlive()) { 82 if (t.getState().equals(State.BLOCKED)) 83 fail("Deadlock detected"); 84 else 85 fail("Test not conclusive: "+ 86 "Thread is alive but not blocked."); 87 } 88 } catch (Throwable e) { 89 e.printStackTrace(System.out); 90 fail(e.toString()); 91 } 92 } 93 94 public void postDeregister() {} 95 96 private final MBeanServer mbs; 97 private final ObjectName otherName; 98 } 99 100 public static void main(String[] args) throws Exception { 101 String previous = null; 102 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); 103 ObjectName on1 = new ObjectName("a:type=Blibby,name=\"1\""); 104 ObjectName on2 = new ObjectName("a:type=Blibby,name=\"2\""); 105 106 107 // Test 1: 108 // 1 MBean is registered with on1 109 // Another MBean is registered with on1, postRegister(FALSE) is 110 // called, and the second MBean attempts to unregister first MBean in 111 // postRegister: 112 // postRegister starts a thread which unregisters the first MBean: 113 // this must not deadlock 114 // 115 System.out.println("\n**** TEST #1 ****\n"); 116 System.out.println("Registering Blibby #1 with name: " + on1); 117 mbs.registerMBean(new Blibby(mbs, null), on1); 118 try { 119 System.out.println("Registering Blibby #2 with same name: " + on1); 120 mbs.registerMBean(new Blibby(mbs, on1), on1); 121 } catch (InstanceAlreadyExistsException x) { 122 System.out.println("Received expected exception: " + x); 123 } 124 if (mbs.isRegistered(on1)) { 125 try { 126 mbs.unregisterMBean(on1); 127 if (failure == null) 128 fail(on1+" should have been unregistered"); 129 } catch (InstanceNotFoundException x) { 130 // Race condition! 131 System.out.println(on1+" was unregistered by mbean thread."); 132 } 133 } else { 134 System.out.println(on1+" was correctly unregistered."); 135 } 136 137 if (failure == previous) 138 System.out.println("\n**** TEST #1 PASSED ****\n"); 139 140 previous = failure; 141 142 // Test 2: 143 // 1 MBean is registered with on1 144 // Another MBean is registered with on2, postRegister(TRUE) is 145 // called, and the second MBean attempts to unregister first MBean in 146 // postRegister: 147 // postRegister starts a thread which unregisters the first MBean: 148 // this must not deadlock 149 // 150 System.out.println("\n**** TEST #2 ****\n"); 151 System.out.println("Registering Blibby #1 with name: " + on1); 152 mbs.registerMBean(new Blibby(mbs, null), on1); 153 System.out.println("Registering Blibby #2 with other name: " + on2); 154 mbs.registerMBean(new Blibby(mbs, on1), on2); 155 if (mbs.isRegistered(on1)) { 156 try { 157 mbs.unregisterMBean(on1); 158 if (failure == null) 159 fail(on1+" should have been unregistered"); 160 } catch (InstanceNotFoundException x) { 161 // Race condition! 162 System.out.println(on1+" was unregistered by mbean thread."); 163 } 164 } else { 165 System.out.println(on1+" was correctly unregistered."); 166 } 167 168 System.out.println("unregistering "+on2); 169 mbs.unregisterMBean(on2); 170 if (failure == previous) 171 System.out.println("\n**** TEST #2 PASSED ****\n"); 172 previous = failure; 173 174 if (failure == null) 175 System.out.println("OK: Test passed"); 176 else 177 throw new Exception("TEST FAILED: " + failure); 178 } 179 180 private static void fail(String why) { 181 System.out.println("FAILED: " + why); 182 failure = (failure == null)?why:(failure+",\n"+why); 183 } 184 185 private static volatile String failure; 186} 187