6042N/A/*
6042N/A * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
6042N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6042N/A *
6042N/A * This code is free software; you can redistribute it and/or modify it
6042N/A * under the terms of the GNU General Public License version 2 only, as
6042N/A * published by the Free Software Foundation.
6042N/A *
6042N/A * This code is distributed in the hope that it will be useful, but WITHOUT
6042N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6042N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
6042N/A * version 2 for more details (a copy is included in the LICENSE file that
6042N/A * accompanied this code).
6042N/A *
6042N/A * You should have received a copy of the GNU General Public License version
6042N/A * 2 along with this work; if not, write to the Free Software Foundation,
6042N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6042N/A *
6042N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6042N/A * or visit www.oracle.com if you need additional information or have any
6042N/A * questions.
6042N/A */
6042N/Aimport java.lang.management.ThreadInfo;
6042N/Aimport java.lang.management.ThreadMXBean;
6042N/Aimport java.lang.Thread.State;
6042N/Aimport java.io.IOException;
6042N/Aimport java.lang.management.ManagementFactory;
6042N/Aimport java.util.logging.LogManager;
6042N/Aimport java.util.logging.Logger;
6042N/Aimport java.util.Map;
6042N/A
6042N/A/**
6042N/A * @test
6042N/A * @bug 8010939
6042N/A * @summary check for deadlock between findLogger() and drainLoggerRefQueueBounded()
6042N/A * @author jim.gish@oracle.com
6042N/A * @build DrainFindDeadlockTest
6042N/A * @run main/othervm/timeout=10 DrainFindDeadlockTest
6042N/A */
6042N/A
6042N/A/**
6042N/A * This test is checking for a deadlock between
6042N/A * LogManager$LoggerContext.findLogger() and
6042N/A * LogManager.drainLoggerRefQueueBounded() (which could happen by calling
6042N/A * Logger.getLogger() and LogManager.readConfiguration() in different threads)
6042N/A */
6042N/Apublic class DrainFindDeadlockTest {
6042N/A private LogManager mgr = LogManager.getLogManager();
6042N/A private final static int MAX_ITERATIONS = 100;
6042N/A
6042N/A // Get a ThreadMXBean so we can check for deadlock. N.B. this may
6042N/A // not be supported on all platforms, which means we will have to
6042N/A // resort to the traditional test timeout method. However, if
6042N/A // we have the support we'll get the deadlock details if one
6042N/A // is detected.
6042N/A private final static ThreadMXBean threadMXBean =
6042N/A ManagementFactory.getThreadMXBean();
6042N/A private final boolean threadMXBeanDeadlockSupported =
6042N/A threadMXBean.isSynchronizerUsageSupported();
6042N/A
6042N/A public static void main(String... args) throws IOException, Exception {
6042N/A new DrainFindDeadlockTest().testForDeadlock();
6042N/A }
6042N/A
6042N/A public static void randomDelay() {
6042N/A int runs = (int) Math.random() * 1000000;
6042N/A int c = 0;
6042N/A
6042N/A for (int i=0; i<runs; ++i) {
6042N/A c=c+i;
6042N/A }
6042N/A }
6042N/A
6042N/A public void testForDeadlock() throws IOException, Exception {
6042N/A System.out.println("Deadlock detection "
6042N/A + (threadMXBeanDeadlockSupported ? "is" : "is not") +
6042N/A " available.");
6042N/A Thread setup = new Thread(new SetupLogger(), "SetupLogger");
6042N/A Thread readConfig = new Thread(new ReadConfig(), "ReadConfig");
6042N/A Thread check = new Thread(new DeadlockChecker(setup, readConfig),
6042N/A "DeadlockChecker");
6042N/A
6042N/A // make the threads daemon threads so they will go away when the
6042N/A // test exits
6042N/A setup.setDaemon(true);
6042N/A readConfig.setDaemon(true);
6042N/A check.setDaemon(true);
6042N/A
6042N/A check.start(); setup.start(); readConfig.start();
6042N/A try {
6042N/A check.join();
6042N/A } catch (InterruptedException ex) {
6042N/A ex.printStackTrace();
6042N/A }
6042N/A try {
6042N/A readConfig.join();
6042N/A setup.join();
6042N/A } catch (InterruptedException ex) {
6042N/A ex.printStackTrace();
6042N/A }
6042N/A System.out.println("Test passed");
6042N/A }
6042N/A
6042N/A class SetupLogger implements Runnable {
6042N/A Logger logger = null;
6042N/A
6042N/A @Override
6042N/A public void run() {
6042N/A System.out.println("Running " + Thread.currentThread().getName());
6042N/A
6042N/A for (int i=0; i < MAX_ITERATIONS; i++) {
6042N/A logger = Logger.getLogger("DrainFindDeadlockTest"+i);
6042N/A DrainFindDeadlockTest.randomDelay();
6042N/A }
6042N/A }
6042N/A }
6042N/A
6042N/A class ReadConfig implements Runnable {
6042N/A @Override
6042N/A public void run() {
6042N/A System.out.println("Running " + Thread.currentThread().getName());
6042N/A for (int i=0; i < MAX_ITERATIONS; i++) {
6042N/A try {
6042N/A mgr.readConfiguration();
6042N/A } catch (IOException | SecurityException ex) {
6042N/A throw new RuntimeException("FAILED: test setup problem", ex);
6042N/A }
6042N/A DrainFindDeadlockTest.randomDelay();
6042N/A }
6042N/A }
6042N/A }
6042N/A
6042N/A class DeadlockChecker implements Runnable {
6042N/A Thread t1, t2;
6042N/A
6042N/A DeadlockChecker(Thread t1, Thread t2) {
6042N/A this.t1 = t1;
6042N/A this.t2 = t2;
6042N/A }
6042N/A
6042N/A void checkState(Thread x, Thread y) {
6042N/A // System.out.println("checkstate");
6042N/A boolean isXblocked = x.getState().equals(State.BLOCKED);
6042N/A boolean isYblocked = y.getState().equals(State.BLOCKED);
6042N/A long[] deadlockedThreads = null;
6042N/A
6042N/A if (isXblocked && isYblocked) {
6042N/A System.out.println("threads blocked");
6042N/A // they are both blocked, but this doesn't necessarily mean
6042N/A // they are deadlocked
6042N/A if (threadMXBeanDeadlockSupported) {
6042N/A System.out.println("checking for deadlock");
6042N/A deadlockedThreads = threadMXBean.findDeadlockedThreads();
6042N/A } else {
6042N/A System.out.println("Can't check for deadlock");
6042N/A }
6042N/A if (deadlockedThreads != null) {
6042N/A System.out.println("We detected a deadlock! ");
6042N/A ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(
6042N/A deadlockedThreads, true, true);
6042N/A for (ThreadInfo threadInfo: threadInfos) {
6042N/A System.out.println(threadInfo);
6042N/A }
6042N/A throw new RuntimeException("TEST FAILED: Deadlock detected");
6042N/A }
6042N/A System.out.println("We may have a deadlock");
6042N/A Map<Thread, StackTraceElement[]> threadMap =
6042N/A Thread.getAllStackTraces();
6042N/A dumpStack(threadMap.get(x), x);
6042N/A dumpStack(threadMap.get(y), y);
6042N/A }
6042N/A }
6042N/A
6042N/A private void dumpStack(StackTraceElement[] aStackElt, Thread aThread) {
6042N/A if (aStackElt != null) {
6042N/A System.out.println("Thread:" + aThread.getName() + ": " +
6042N/A aThread.getState());
6042N/A for (StackTraceElement element: aStackElt) {
6042N/A System.out.println(" " + element);
6042N/A }
6042N/A }
6042N/A }
6042N/A
6042N/A @Override
6042N/A public void run() {
6042N/A System.out.println("Running " + Thread.currentThread().getName());
6042N/A for (int i=0; i < MAX_ITERATIONS*2; i++) {
6042N/A checkState(t1, t2);
6042N/A try {
6042N/A Thread.sleep(10);
6042N/A } catch (InterruptedException ex) {
6042N/A };
6042N/A }
6042N/A }
6042N/A }
6042N/A}