More improvements to connection reset handling niosocketimpl-branch
authoralanb
Mon, 18 Mar 2019 19:59:05 +0000
branchniosocketimpl-branch
changeset 57270 3519688a4e4d
parent 57268 adcdd45830a0
child 57274 07b6be5d9150
More improvements to connection reset handling
src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java
src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
src/java.base/unix/native/libnio/ch/SocketDispatcher.c
src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java
--- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java	Mon Mar 18 19:59:05 2019 +0000
@@ -78,7 +78,7 @@
  */
 
 public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
-    private static final NativeDispatcher nd = new SocketDispatcher(true);
+    private static final NativeDispatcher nd = new SocketDispatcher();
 
     // The maximum number of bytes to read/write per syscall to avoid needing
     // a huge buffer from the temporary buffer cache
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Mar 18 19:59:05 2019 +0000
@@ -52,6 +52,7 @@
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
+import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
 import sun.net.ext.ExtendedSocketOptions;
 import sun.net.util.SocketExceptions;
@@ -356,6 +357,8 @@
                 } else {
                     n = IOUtil.read(fd, buf, -1, nd);
                 }
+            } catch (ConnectionResetException e) {
+                throw new IOException(e.getMessage());
             } finally {
                 endRead(blocking, n > 0);
                 if (n <= 0 && isInputClosed)
@@ -391,6 +394,8 @@
                 } else {
                     n = IOUtil.read(fd, dsts, offset, length, nd);
                 }
+            } catch (ConnectionResetException e) {
+                throw new IOException(e.getMessage());
             } finally {
                 endRead(blocking, n > 0);
                 if (n <= 0 && isInputClosed)
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Mon Mar 18 19:59:05 2019 +0000
@@ -34,26 +34,28 @@
  */
 
 class SocketDispatcher extends NativeDispatcher {
-    private final boolean detectConnectionReset;
+    SocketDispatcher() { }
 
-    SocketDispatcher(boolean detectConnectionReset) {
-        this.detectConnectionReset = detectConnectionReset;
-    }
-
-    SocketDispatcher() {
-        this(false);
+    /**
+     * Reads up to len bytes from a socket with special handling for "connection
+     * reset".
+     *
+     * @throws sun.net.ConnectionResetException if connection reset is detected
+     * @throws IOException if another I/O error occurs
+     */
+    int read(FileDescriptor fd, long address, int len) throws IOException {
+        return read0(fd, address, len);
     }
 
-    int read(FileDescriptor fd, long address, int len) throws IOException {
-        if (detectConnectionReset) {
-            return read0(fd, address, len);
-        } else {
-            return FileDispatcherImpl.read0(fd, address, len);
-        }
-    }
-
+    /**
+     * Scattering read from a socket into len buffers with special handling for
+     * "connection reset".
+     *
+     * @throws sun.net.ConnectionResetException if connection reset is detected
+     * @throws IOException if another I/O error occurs
+     */
     long readv(FileDescriptor fd, long address, int len) throws IOException {
-        return FileDispatcherImpl.readv0(fd, address, len);
+        return readv0(fd, address, len);
     }
 
     int write(FileDescriptor fd, long address, int len) throws IOException {
@@ -74,16 +76,12 @@
 
     // -- Native methods --
 
-    /**
-     * Reads up to len bytes from a socket with special handling for "connection
-     * reset".
-     *
-     * @throws sun.net.ConnectionResetException if connection reset is detected
-     * @throws IOException if another I/O error occurs
-     */
     private static native int read0(FileDescriptor fd, long address, int len)
         throws IOException;
 
+    private static native long readv0(FileDescriptor fd, long address, int len)
+        throws IOException;
+
     static {
         IOUtil.load();
     }
--- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Mon Mar 18 19:59:05 2019 +0000
@@ -31,6 +31,8 @@
 import java.util.concurrent.*;
 import java.io.IOException;
 import java.io.FileDescriptor;
+
+import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
 import sun.net.util.SocketExceptions;
 import sun.security.action.GetPropertyAction;
@@ -415,6 +417,8 @@
             enableReading();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
+            if (x instanceof ConnectionResetException)
+                x = new IOException(x.getMessage());
             exc = x;
         } finally {
             // restart poll in case of concurrent write
@@ -546,6 +550,8 @@
         } catch (Throwable x) {
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
+            if (x instanceof ConnectionResetException)
+                x = new IOException(x.getMessage());
             exc = x;
         } finally {
             if (!pending)
--- a/src/java.base/unix/native/libnio/ch/SocketDispatcher.c	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/unix/native/libnio/ch/SocketDispatcher.c	Mon Mar 18 19:59:05 2019 +0000
@@ -24,6 +24,7 @@
  */
 
  #include <sys/types.h>
+ #include <sys/uio.h>
  #include <unistd.h>
 
  #include "jni.h"
@@ -47,3 +48,18 @@
          return convertReturnVal(env, n, JNI_TRUE);
      }
  }
+
+ JNIEXPORT jlong JNICALL
+ Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz,
+                                         jobject fdo, jlong address, jint len)
+ {
+     jint fd = fdval(env, fdo);
+     struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+     jlong n = readv(fd, iov, len);
+     if ((n == -1) && (errno == ECONNRESET || errno == EPIPE)) {
+         JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
+         return IOS_THROWN;
+     } else {
+         return convertLongReturnVal(env, n, JNI_TRUE);
+     }
+ }
--- a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java	Sat Mar 16 21:00:45 2019 +0000
+++ b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java	Mon Mar 18 19:59:05 2019 +0000
@@ -33,11 +33,8 @@
  */
 
 class SocketDispatcher extends NativeDispatcher {
-
     SocketDispatcher() { }
 
-    SocketDispatcher(boolean ignore) { }
-
     int read(FileDescriptor fd, long address, int len) throws IOException {
         return read0(fd, address, len);
     }