2362N/A * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * @summary Tests NotificationBuffer doesn't hold locks when adding listeners. 0N/A * @author Eamonn McManus 0N/A * @run clean NotificationBufferDeadlockTest 0N/A * @run build NotificationBufferDeadlockTest 0N/A * @run main NotificationBufferDeadlockTest 0N/A * Regression test for a rare but not unheard-of deadlock condition in 0N/A * the notification buffer support for connector servers. 0N/A * See bug 6239400 for the description of the bug and the example that 0N/A * Here we test that, when the connector server adds its listener to an 0N/A * MBean, it is not holding a lock that would prevent another thread from 0N/A * emitting a notification (from that MBean or another one). This is 0N/A * important, because we don't know how user MBeans might implement 0N/A * NotificationBroadcaster.addNotificationListener, and in particular we 0N/A * can't be sure that the method is well-behaved and can never do a 0N/A * blocking operation, such as attempting to acquire a lock that is also 0N/A * acquired when notifications are emitted. 0N/A * The test creates a special MBean whose addNotificationListener method 0N/A * does the standard addNotificationListener logic inherited 0N/A * from NotificationBroadcasterSupport, then 0N/A * creates another thread that emits a notification from the same MBean. 0N/A * The addNotificationListener method waits for this thread to complete. 0N/A * If the notification buffer logic is incorrect, then emitting the 0N/A * notification will attempt to acquire the lock on the buffer, but that 0N/A * lock is being held by the thread that called addNotificationListener, 0N/A * so there will be deadlock. 0N/A * We use this DeadlockMBean several times. First, we create one and then 0N/A * add a remote listener to it. The first time you add a remote listener 0N/A * through a connector server, the connector server adds its own listener 0N/A * to all NotificationBroadcaster MBeans. If it holds a lock while doing 0N/A * this, we will see deadlock. 0N/A * Then we create a second DeadlockMBean. When a new MBean is created that 0N/A * is a NotificationBroadcaster, the connector server adds its listener to 0N/A * that MBean too. Again if it holds a lock while doing this, we will see 0N/A * Finally, we do some magic with MBeanServerForwarders so that while 0N/A * queryNames is running (to find MBeans to which listeners must be added) 0N/A * we will create new MBeans. This tests that this tricky situation is 0N/A * handled correctly. It also tests the queryNames that is run when the 0N/A * notification buffer is being destroyed (to remove the listeners). 0N/A * We cause all of our test MBeans to emit exactly one notification and 0N/A * check that we have received exactly one notification from each MBean. 0N/A * If the logic for adding the notification buffer's listener is incorrect 0N/A * we could remove zero or two notifications from an MBean. 0N/A "remote listeners being added");
0N/A return "did not get " +
names.
size() +
" notifs as expected\n";
0N/A synchronized(
this) {
0N/A synchronized(
this) {