Name: nt126004 Date: 09/09/2002 FULL PRODUCT VERSION : java version "1.4.1-rc" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19) Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode) FULL OPERATING SYSTEM VERSION : SunOs sss1 5.8 Generic_108528-13 sun4u sparc SUNW,Ultra-80 A DESCRIPTION OF THE PROBLEM : Closing a SelectableChannel in one thread and calling Selector.select() in another thread may result in a deadlock situation (the channel being registred with the selector). The reason is both SelectableChannel.close() and Selector.select() synchronize on the same couple of objects but in a different order as the following stack trace shows: CLOSE (Thread A): ================= java.nio.channels.spi.AbstractSelector.cancel() => enter monitor for a java.util.HashSet (protecting this selector's cancelled key list) java.nio.channels.spi.AbstractSelectionKey.cancel() java.nio.channels.spi.AbstractSelectableChannel.implCloseCha nnel() => enter monitor for a java.lang.Object (protecting this channel's keys) java.nio.channels.spi.AbstractInterruptibleChannel.close() SELECT (Thread B): ================== java.nio.channels.spi.AbstractSelectableChannel.removeKey () => enter monitor for a java.lang.Object (protecting this channel's keys) java.nio.channels.spi.AbstractSelector.deregister() sun.nio.ch.DevPollSelectorImpl.implDereg() sun.nio.ch.SelectorImpl.processDeregisterQueue() => enter monitor for a java.util.HashSet (protecting this selector's cancelled key list) sun.nio.ch.DevPollSelectorImpl.doSelect() sun.nio.ch.SelectorImpl.select() It is possible that Thread A acquires a lock on the Object then Thread B acquires a lock on the HashSet before Thread A. This results in a deadlock. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Run the example code under a Thread Analyser (e.g. OptimizeIt). Note: deadlock is unreproductible but thread / source code analysis shows it can happen. REPRODUCIBILITY : This bug can be reproduced rarely. ---------- BEGIN SOURCE ---------- import java.nio.channels.*; public class Deadlock { public static void main(String[] args) throws Exception { final Selector selector = Selector.open(); Thread thread = new Thread(new Runnable() { public void run() { while (true) { try { System.out.println("select"); selector.select(100); } catch (Exception e) {} } } }); thread.start(); while (true) { SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); channel.register(selector, 0, null); System.out.println("close"); channel.close(); } } } ---------- END SOURCE ---------- (Review ID: 164121) ======================================================================
|