Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6841139
Votes 2
Synopsis Cant detect deadlock when thread reenters synchronization block in Object.wait()
Category java:classes_management
Reported Against
Release Fixed
State 1-Dispatched, bug
Priority: 4-Low
Related Bugs
Submit Date 14-MAY-2009
Description
FULL PRODUCT VERSION :
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
 customer  Windows [Version 5.2.3790]


A DESCRIPTION OF THE PROBLEM :
Methods ThreadMXBean.findMonitorDeadlockedThreads() and ThreadMXBean.findDeadlockedThreads()  are unable to detect deadlock when one thread reenters synchronization block after Object.wait() call in case of pure monitors or after java.util.concurrent.locks.Condition.await() call in case of ReentrantLock or ReentrantReadWriteLock.

see test case below

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
unable to detect deadlock
ACTUAL -
such deadlock should be detected

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class FindDeadlockTest {
	private ThreadMXBean threadMxBean;

	@Before
	public void setUp() {
		threadMxBean = ManagementFactory.getThreadMXBean();
	}

	@Test
	public void testMonitorReacquiranceFromWait() {
		final Object LOCK0 = new Object();
		final Object LOCK1 = new Object();
		String threadNamePrefix = "MonitorReacquiranceFromWait";
		start(threadNamePrefix + "-0", new Runnable() {
			public void run() {
				try {
					synchronized (LOCK0) {
						synchronized (LOCK1) {
							LOCK0.wait();
						}
					}
				} catch (InterruptedException exc) {
					// ignore
				}
			}
		});
		start(threadNamePrefix + "-1", new Runnable() {
			public void run() {
				sleep(1000);
				synchronized (LOCK0) {
					LOCK0.notify();
					synchronized (LOCK1) {
						// no nothing
					}
				}
			}
		});
		sleep(2000);
		check(threadNamePrefix, threadMxBean.findMonitorDeadlockedThreads(), 2);
		check(threadNamePrefix, threadMxBean.findDeadlockedThreads(), 2);
	}

	@Test
	public void testReentrantLockReacquiranceFromAwait() {
		final Lock LOCK0 = new ReentrantLock();
		final Lock LOCK1 = new ReentrantLock();
//		final Lock LOCK0 = new ReentrantReadWriteLock().writeLock();
//		final Lock LOCK1 = new ReentrantReadWriteLock().writeLock();
		final Condition COND0 = LOCK0.newCondition();
		String threadNamePrefix = "ReentrantLockReacquiranceFromAwait";
		start(threadNamePrefix + "-0", new Runnable() {
			public void run() {
				try {
					LOCK0.lock();
					try {
						LOCK1.lock();
						try {
							COND0.await();
						} finally {
							LOCK1.unlock();
						}
					} finally {
						LOCK0.unlock();
					}
				} catch (InterruptedException exc) {
					// ignore
				}
			}
		});
		start(threadNamePrefix + "-1", new Runnable() {
			public void run() {
				sleep(1000);
				LOCK0.lock();
				try {
					COND0.signal();
					LOCK1.lock();
					try {
						// no nothing
					} finally {
						LOCK1.unlock();
					}
				} finally {
					LOCK0.unlock();
				}
			}
		});
		sleep(2000);
		check(threadNamePrefix, threadMxBean.findDeadlockedThreads(), 2);
	}

	static void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException exc) {
			// ignore
		}
	}

	static void start(String name, Runnable r) {
		Thread thread = new Thread(r, name);
		thread.setDaemon(true);
		thread.start();
	}

	void check(String threadNamePrefix, long[] ids, int expectedNumberOfDeadlockedThreads) {
		int actualNumberOfDeadlockedThreads = 0;
		if (ids != null) {
			for (ThreadInfo info : threadMxBean.getThreadInfo(ids)) {
				if (info.getThreadName().startsWith(threadNamePrefix)) {
					++actualNumberOfDeadlockedThreads;
				}
			}
		}
		Assert.assertEquals("number of deadlocked threads", expectedNumberOfDeadlockedThreads, actualNumberOfDeadlockedThreads);
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
use own code for deadlock detection
Posted Date : 2009-05-14 14:33:40.0
Work Around
N/A
Evaluation
N/A
Comments
  
  Include a link with my name & email   

Submitted On 23-JUL-2009
dmytro_sheyko
https://bugs.openjdk.java.net/show_bug.cgi?id=100058



PLEASE NOTE: JDK6 is formerly known as Project Mustang