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 darden 5.8 Generic_108528-06 sun4u sparc SUNW,Ultra-5_10
ADDITIONAL OPERATING SYSTEMS :
Linux mango 2.4.7-10 #1 Thu Sep 6 17:27:27 EDT 2001 i686
unknown
A DESCRIPTION OF THE PROBLEM :
When implCloseChannel() is called in
AbstractSelectableChannel not all the keys are canceled,
which keeps the connection from closing.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Register a SelectableChannel with Selector A.
2. Register the same channel with Selector B.
3. Cancel the channel's key from Selector A.
4. Close the channel.
This seems to be the result of the following code in
AbstractSelectableChannel:
protected final void implCloseChannel() throws IOException {
implCloseSelectableChannel();
synchronized (keyLock) {
for (int i = 0; i < keyCount; i++) {
SelectionKey k = keys[i];
if (k != null)
k.cancel();
}
}
}
keyCount should be keys.length
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected results are that both selectors will contain zero
SelectableKeys and the channel will be closed. Actual
result is that the channel is still open and the key is
still in SelectorB.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
public class MultiSelectorTestServer {
private static ServerSocketChannel ssc;
private static Selector connectSelector;
private static Selector selectorA;
private static Selector selectorB;
public static void main(String args[]) {
InetSocketAddress address = new InetSocketAddress(8888);
try {
connectSelector = Selector.open();
selectorA = Selector.open();
selectorB = Selector.open();
ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(address);
ssc.register(connectSelector, SelectionKey.OP_ACCEPT);
print("Bound to " + address);
}
catch(Exception e) {
print(e);
}
while (true) {
try {
connectSelector.select();
acceptPendingConnections();
} catch (Exception e) {
print(e);
}
}
}
private static void acceptPendingConnections() throws Exception {
ServerSocketChannel readyChannel;
SocketChannel incomingChannel;
Set readyKeys = connectSelector.selectedKeys();
for (Iterator i = readyKeys.iterator(); i.hasNext(); ) {
SelectionKey key = (SelectionKey) i.next();
i.remove();
readyChannel = (ServerSocketChannel) key.channel();
incomingChannel = readyChannel.accept();
incomingChannel.configureBlocking(false);
incomingChannel.register(selectorA, SelectionKey.OP_READ);
incomingChannel.register(selectorB, SelectionKey.OP_READ);
print("\nAccepting connection from " + incomingChannel.socket
());
print("selectorA contains " + selectorA.keys().size()+ "
keys.");
print("selectorB contains " + selectorB.keys().size()+ "
keys.");
print("\ncancelling key with selectorA");
incomingChannel.keyFor(selectorA).cancel();
selectorA.select(1);
print("selectorA contains " + selectorA.keys().size()+ "
keys.");
print("selectorB contains " + selectorB.keys().size()+ "
keys.");
print("\nclosing channel, both keys should be cancelled,
connection should be closed.");
incomingChannel.close();
selectorB.select(1);
selectorA.select(1);
print("selectorA contains " + selectorA.keys().size()+ "
keys.");
print("selectorB contains " + selectorB.keys().size()+ "
keys.");
print("connection is open: " + incomingChannel.isOpen());
}
}
public static void print(Object obj) {
System.out.println(obj);
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Manually remove the channel's keys with each selector
before closing the channel.
(Review ID: 164116)
======================================================================
- relates to
-
JDK-4684637 (ch) AssertionError in AbstractSelectableChannel
-
- Closed
-