United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6346658 (se) Selector briefly spins when asynchronously closing a registered channel [win]
JDK-6346658 : (se) Selector briefly spins when asynchronously closing a registered channel [win]

Details
Type:
Bug
Submit Date:
2005-11-07
Status:
Closed
Updated Date:
2013-12-23
Project Name:
JDK
Resolved Date:
2012-06-20
Component:
core-libs
OS:
generic,solaris_10,windows_xp,windows_7
Sub-Component:
java.nio
CPU:
x86,sparc,generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0,6,7
Fixed Versions:

Related Reports
Backport:
Backport:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
Mustang b59 fastdebug

ADDITIONAL OS VERSION INFORMATION :
XP SP 2

A DESCRIPTION OF THE PROBLEM :
I have a select loop, selector is blocked with one key, a socketchannel, interest set = 0. When another thread calls SocketChannel#close, the select wakes up, no keys selected. The loop spins several times until the connection is finally closed.

Thread state when select first wakes up:

Thread-0@d8 prio=5, in group "main", status: RUNNING
	  close0():-1, SocketDispatcher.java
	  preClose():44, SocketDispatcher.java
	  implCloseSelectableChannel():630, SocketChannelImpl.java
	  implCloseChannel():201, AbstractSelectableChannel.java
	  close():97, AbstractInterruptibleChannel.java
	  run():33, SelectBlocks.java

...

main@2 prio=5, in group "main", status: RUNNING
	  main():44, SelectBlocks.java



According to my understanding the selector shouldn't wake up at all. And certainly not spin.

I see a similar phenomenon on Solaris 10 / AMD x64.
No wakeup with 1.5_05, only one "spurious" wakeup with b59:

% uname -a
SunOS sol10sqa 5.10 Generic i86pc i386 i86pc

Accepted connection = java.nio.channels.SocketChannel[connected local=/10.2.2.22:56420 remote=/10.2.2.22:56421]
Closing connection
Closed connection
Selector: 0/1
Selector: 0/0


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program. It will open a connection to itself, select on it and close it after one second. It will print a line for each time select wakes up.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
JDK 1.5.0_05:

  Accepted connection = java.nio.channels.SocketChannel[connected local=/169.254.69.42:2632 remote=/169.254.69.42:2633]
Closing connection
  Closed connection
Selector: 0/0

ACTUAL -
  Accepted connection = java.nio.channels.SocketChannel[connected local=/169.254.69.42:2684 remote=/169.254.69.42:2685]
Closing connection
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Selector: 0/1
Closed connection
Selector: 0/0


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * Copyright (c) 2005 Matthias Ernst, Hamburg. All rights reserved.
 */
package test.nio;


import java.io.IOException;
import java.net.Socket;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class SelectBlocks {
  public static void main(String[] args) throws IOException {
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.socket().bind(null);

    new Socket(serverSocketChannel.socket().getInetAddress(), serverSocketChannel.socket().getLocalPort());
    final SocketChannel connection = serverSocketChannel.accept();

    System.out.println("Accepted connection = " + connection);

    connection.configureBlocking(false);

    final Selector selector = Selector.open();
    connection.register(selector, 0);

    new Thread() {
      public void run() {
        try {
          Thread.sleep(1000);
          System.out.println("Closing connection");
          connection.close();
          System.out.println("Closed connection");
          selector.wakeup();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }.start();

    while(true) {
      selector.select();
      System.out.println("Selector: "+selector.selectedKeys().size()+"/"+selector.keys().size());
      selector.selectedKeys().clear();
    }
  }
}

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

                                    

Comments
EVALUATION

The fix for 4960962 in b33 means that the channel is closed prior to the cancel of the channel's keys. As a result the Windows Selector will get an error when it polls. This will be observed as the Selector spinning as per the submitter's test case. The spinning will stop once the closed channel's keys have been canncelled. We need to revisit the for the 4960962 to see if an alternative solution is possible.
                                     
2005-11-08
EVALUATION

The reason this "spin up" does not happens in previous releases
is that the previous releases failed to actually close/shutdown
the connection, which they should. Seems like somehow the "channel
closing" thread suddently got slowdown after it called preClose, it
appears the thread waited somewhere (probably waiting to get the
"keylock"?) for a while before it can do the real key cancellation.
Meanwhile the selector keeps spinning, because the key is not
cancelled yet and the key has ZERO in its interesting set (so we
dont put it into the selectedKeys).

A possible solution is to withdraw the fd out of the native selecting/
polling pool when we find we have a select error (fd is not an
available handle/socket), the related channel actually has been
closed AND the key actually has ZERO interesting...but too late/
risky for mustang, given the "problem" is not that severe/damaging,
the key will get cancelled sonner or latter (except the closing
thread gets killed), the program should be aware that the select()
may return 0 and in normal case the interesting set should not
be empty (then the key is selected).
                                     
2005-12-09
EVALUATION

We have changed the implementation so that the asynchronous close of channels registered with a Selector is done cooperatively. These changes should be in jdk8-b29.
                                     
2012-02-20



Hardware and Software, Engineered to Work Together