Name: nt126004 Date: 06/03/2002
FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-
b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
SUSE Linux 2.4.10-4, glibc-2.2.4-64
A DESCRIPTION OF THE PROBLEM :
The documentation for java.nio.Selector states: "The selection
operations synchronize on the selector itself, on the key set, and on the
selected-key set, in that order. They also synchronize on the cancelled-
key set during steps (1) and (3) above."
However, synchronizing on
the selector from another thread does not appear to prevent a selection
operation from occurring.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. From a separate thread, lock the selector instance, and hold it.
2. From the selection thread, perform a selectNow() or select( long ).
3. Even though the selector lock is being held by another thread, the
selection will complete, and the statements following the selection
are executed.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED
The selection operation should block, because the
selection operation is supposed to obtain a lock on the Selector
instance before proceeding.
ACTUAL
Instead, the selection
operation succeeds. This presents a problem when trying to wakeup the
selector to register a new channel. It is not sufficient to simply call
wakeup() and register() consecutively from another thread, since a
selection operation in a loop can theoretically wakeup, loop around,
and start into another selection before register() is called.
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.nio.channels.*;
public class selectorTest
{
public static void main( String[] args )
throws Throwable
{
final Selector selector = Selector.open();
new Thread()
{
public void run()
{
try{
synchronized( selector )
{
System.out.println( "GOT LOCK" );
synchronized( this )
{
wait();
}
System.out.println( "LETTING GO" );
}
}catch(Exception e )
{System.err.println( e );}
}
}.start();
Thread.currentThread().sleep( 5000 );
System.out.println("SELECTING" );
selector.select(3000);
System.out.println( "SHOULD NOT OCCUR" );
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Manually do the synchronization. That is, synchronize on any object and
release the lock immediately before doing a selection. Thus another
thread can synchronize on that object, before waking the selection
thread up, preventing it from looping around into another selection
operation before the other thread is finished.
(Review ID: 147304)
======================================================================