JDK-6346658 : (se) Selector briefly spins when asynchronously closing a registered channel [win]
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 5.0,6,7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,solaris_10,windows_xp,windows_7 generic,solaris_10,windows_xp,windows_7
  • CPU: generic,x86,sparc
  • Submitted: 2005-11-07
  • Updated: 2017-05-16
  • Resolved: 2012-06-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 JDK 8
6u71Fixed 7u6Fixed 8 b28Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
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 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.
20-02-2012

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).
09-12-2005

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.
08-11-2005