JDK-8260875 : (sc)SocketAdaptor$SocketInputStream read throws IllegalBlockingModeException on closed channel
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2021-02-02
  • Updated: 2021-02-02
  • Resolved: 2021-02-02
Related Reports
Duplicate :  
Description
$ cat NIOTest.java
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class NIOTest {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel server = ServerSocketChannel.open();
        server.bind(null);
        SocketAddress saddr = server.getLocalAddress();
        Thread t = new Thread(() -> {
            try {
                SocketChannel channel = SocketChannel.open(saddr);
                Socket s = channel.socket();
                s.setSoTimeout(10000);
                InputStream is = s.getInputStream();

                byte[] buf = new byte[10];
                try {
                    is.read(buf);
                } catch (Exception e) {
                    // now channel is closed
                    is.read(buf);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        t.start();
        Thread.sleep(1000);
        t.interrupt();
    }
}

$ java NIOTest(jdk 8)
java.nio.channels.IllegalBlockingModeException
        at sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:202)
        at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
        at java.io.InputStream.read(InputStream.java:101)
        at NIOTest.lambda$main$0(NIOTest.java:24)
        at java.lang.Thread.run(Thread.java:748)


$java NIOTest(jdk 11)
java.nio.channels.AsynchronousCloseException
        at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:202)
        at java.base/sun.nio.ch.SocketChannelImpl.endRead(SocketChannelImpl.java:334)
        at java.base/sun.nio.ch.SocketChannelImpl.pollRead(SocketChannelImpl.java:970)
        at java.base/sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:209)
        at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
        at java.base/java.io.InputStream.read(InputStream.java:205)
        at NIOTest.lambda$main$0(NIOTest.java:24)
        at java.base/java.lang.Thread.run(Thread.java:834)


$java NIOTest(jdk/jdk)
java.nio.channels.ClosedChannelException
        at java.base/sun.nio.ch.SocketChannelImpl.ensureOpenAndConnected(SocketChannelImpl.java:215)
        at java.base/sun.nio.ch.SocketChannelImpl.blockingRead(SocketChannelImpl.java:1254)
        at java.base/sun.nio.ch.SocketAdaptor$1.read(SocketAdaptor.java:191)
        at java.base/java.io.InputStream.read(InputStream.java:218)
        at NIOTest.lambda$main$0(NIOTest.java:24)
        at java.base/java.lang.Thread.run(Thread.java:831)

Backport JDK-8246707 to 11 can solve the problem of 11, but it cannot backport to 8 because SocketChannel implementation was refactored in JDK 11




Proposed fix:
diff -r b54c25e76b6d src/share/classes/sun/nio/ch/SocketAdaptor.java
--- a/src/share/classes/sun/nio/ch/SocketAdaptor.java   Fri Jan 15 17:21:26 2021 +0000
+++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java   Tue Feb 02 09:13:53 2021 +0800
@@ -198,6 +198,8 @@
             throws IOException
         {
             synchronized (sc.blockingLock()) {
+                if (!sc.isOpen())
+                    throw new ClosedChannelException();
                 if (!sc.isBlocking())
                     throw new IllegalBlockingModeException();


Comments
Also tracked as JDK-6878250.
02-02-2021