--- a/src/java.base/share/classes/java/net/ServerSocket.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/java/net/ServerSocket.java Wed Mar 20 13:54:50 2019 +0000
@@ -758,7 +758,7 @@
if (isClosed())
throw new SocketException("Socket is closed");
if (timeout < 0)
- throw new IllegalArgumentException("timeout can't be negative");
+ throw new IllegalArgumentException("timeout < 0");
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
}
--- a/src/java.base/share/classes/java/net/Socket.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/java/net/Socket.java Wed Mar 20 13:54:50 2019 +0000
@@ -1221,7 +1221,7 @@
if (isClosed())
throw new SocketException("Socket is closed");
if (timeout < 0)
- throw new IllegalArgumentException("timeout can't be negative");
+ throw new IllegalArgumentException("timeout < 0");
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
}
--- a/src/java.base/share/classes/sun/nio/ch/Net.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/Net.java Wed Mar 20 13:54:50 2019 +0000
@@ -535,9 +535,18 @@
int level, int opt, int arg, boolean isIPv6)
throws IOException;
+ /**
+ * Polls a file descriptor for events.
+ * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
+ * @return the polled events or 0 if no events are polled
+ */
static native int poll(FileDescriptor fd, int events, long timeout)
throws IOException;
+ /**
+ * Performs a non-blocking poll of a file descriptor.
+ * @return the polled events or 0 if no events are polled
+ */
static int pollNow(FileDescriptor fd, int events) throws IOException {
return poll(fd, events, 0);
}
@@ -548,12 +557,18 @@
* @apiNote This method is public to allow it be used by code in jdk.sctp.
*
* @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
- * @return 1 if connected, 0 if not connected, or IOS_INTERRUPTED
+ * @return true if connected
*/
- public static native int pollConnect(FileDescriptor fd, long timeout)
+ public static native boolean pollConnect(FileDescriptor fd, long timeout)
throws IOException;
- static int pollConnectNow(FileDescriptor fd) throws IOException {
+ /**
+ * Performs a non-blocking poll of a connecting socket to test if the
+ * connection has been established.
+ *
+ * @return true if connected
+ */
+ static boolean pollConnectNow(FileDescriptor fd) throws IOException {
return pollConnect(fd, 0);
}
--- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java Wed Mar 20 13:54:50 2019 +0000
@@ -525,22 +525,22 @@
* Waits for a connection attempt to finish with a timeout.
* @throws SocketTimeoutException if the connect timeout elapses
*/
- private int timedFinishConnect(FileDescriptor fd, int millis) throws IOException {
+ private boolean timedFinishConnect(FileDescriptor fd, int millis) throws IOException {
long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
long remainingNanos = nanos;
long startNanos = System.nanoTime();
- int n;
+ boolean connected;
do {
park(fd, Net.POLLOUT, remainingNanos);
- n = Net.pollConnectNow(fd);
- if (n == 0) {
+ connected = Net.pollConnectNow(fd);
+ if (!connected) {
remainingNanos = nanos - (System.nanoTime() - startNanos);
if (remainingNanos <= 0) {
throw new SocketTimeoutException("Connect timed out");
}
}
- } while (n == 0 && isOpen());
- return n;
+ } while (!connected && isOpen());
+ return connected;
}
/**
@@ -572,19 +572,20 @@
try {
configureNonBlockingIfNeeded(fd, millis);
int n = Net.connect(fd, address, port);
- if (IOStatus.okayToRetry(n) && isOpen()) {
+ if (n > 0 && isOpen()) {
+ connected = true;
+ } else if (IOStatus.okayToRetry(n) && isOpen()) {
if (millis > 0) {
// finish connect with timeout
- n = timedFinishConnect(fd, millis);
+ connected = timedFinishConnect(fd, millis);
} else {
// finish connect, no timeout
do {
park(fd, Net.POLLOUT);
- n = Net.pollConnectNow(fd);
- } while (n == 0 && isOpen());
+ connected = Net.pollConnectNow(fd);
+ } while (!connected && isOpen());
}
}
- connected = (n > 0) && isOpen();
} finally {
endConnect(connected);
}
@@ -813,16 +814,13 @@
@Override
protected int available() throws IOException {
- readLock.lock();
- try {
+ synchronized (stateLock) {
ensureOpenAndConnected();
if (isInputClosed) {
return 0;
} else {
return Net.available(fd);
}
- } finally {
- readLock.unlock();
}
}
--- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Wed Mar 20 13:54:50 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -216,6 +216,11 @@
}
}
}
+
+ @Override
+ public int available() throws IOException {
+ return sc.available();
+ }
}
private InputStream socketInputStream = null;
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Mar 20 13:54:50 2019 +0000
@@ -32,6 +32,7 @@
import java.net.ProtocolFamily;
import java.net.Socket;
import java.net.SocketAddress;
+import java.net.SocketException;
import java.net.SocketOption;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions;
@@ -86,6 +87,9 @@
private volatile boolean isInputClosed;
private volatile boolean isOutputClosed;
+ // Connection reset protected by readLock
+ private boolean connectionReset;
+
// -- The following fields are protected by stateLock
// set true when exclusive binding is on and SO_REUSEADDR is emulated
@@ -231,7 +235,7 @@
}
// no options that require special handling
- Net.setSocketOption(fd, Net.UNSPEC, name, value);
+ Net.setSocketOption(fd, name, value);
return this;
}
}
@@ -261,7 +265,7 @@
}
// no options that require special handling
- return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+ return (T) Net.getSocketOption(fd, name);
}
}
@@ -335,6 +339,10 @@
}
}
+ private void throwConnectionReset() throws SocketException {
+ throw new SocketException("Connection reset");
+ }
+
@Override
public int read(ByteBuffer buf) throws IOException {
Objects.requireNonNull(buf);
@@ -346,6 +354,10 @@
try {
beginRead(blocking);
+ // check if connection has been reset
+ if (connectionReset)
+ throwConnectionReset();
+
// check if input is shutdown
if (isInputClosed)
return IOStatus.EOF;
@@ -358,7 +370,8 @@
n = IOUtil.read(fd, buf, -1, nd);
}
} catch (ConnectionResetException e) {
- throw new IOException(e.getMessage());
+ connectionReset = true;
+ throwConnectionReset();
} finally {
endRead(blocking, n > 0);
if (n <= 0 && isInputClosed)
@@ -383,6 +396,10 @@
try {
beginRead(blocking);
+ // check if connection has been reset
+ if (connectionReset)
+ throwConnectionReset();
+
// check if input is shutdown
if (isInputClosed)
return IOStatus.EOF;
@@ -395,7 +412,8 @@
n = IOUtil.read(fd, dsts, offset, length, nd);
}
} catch (ConnectionResetException e) {
- throw new IOException(e.getMessage());
+ connectionReset = true;
+ throwConnectionReset();
} finally {
endRead(blocking, n > 0);
if (n <= 0 && isInputClosed)
@@ -774,15 +792,13 @@
boolean connected = false;
try {
beginFinishConnect(blocking);
- int n = 0;
if (blocking) {
do {
- n = Net.pollConnect(fd, -1);
- } while ((n == 0 || n == IOStatus.INTERRUPTED) && isOpen());
+ connected = Net.pollConnect(fd, -1);
+ } while (!connected && isOpen());
} else {
- n = Net.pollConnect(fd, 0);
+ connected = Net.pollConnect(fd, 0);
}
- connected = (n > 0);
} finally {
endFinishConnect(blocking, connected);
}
@@ -1012,6 +1028,20 @@
}
/**
+ * Return the number of bytes in the socket input buffer.
+ */
+ int available() throws IOException {
+ synchronized (stateLock) {
+ ensureOpenAndConnected();
+ if (isInputClosed) {
+ return 0;
+ } else {
+ return Net.available(fd);
+ }
+ }
+ }
+
+ /**
* Translates native poll revent ops into a ready operation ops
*/
public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java Wed Mar 20 13:54:50 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/java.base/unix/native/libnio/ch/Net.c Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/unix/native/libnio/ch/Net.c Wed Mar 20 13:54:50 2019 +0000
@@ -804,7 +804,7 @@
}
}
-JNIEXPORT jint JNICALL
+JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_pollConnect(JNIEnv *env, jobject this, jobject fdo, jlong timeout)
{
jint fd = fdval(env, fdo);
@@ -835,16 +835,12 @@
return handleSocketError(env, ENOTCONN);
}
// connected
- return 1;
- } else if (result == 0) {
- return 0;
+ return JNI_TRUE;
+ } else if (result == 0 || errno == EINTR) {
+ return JNI_FALSE;
} else {
- if (errno == EINTR) {
- return IOS_INTERRUPTED;
- } else {
- JNU_ThrowIOExceptionWithLastError(env, "poll failed");
- return IOS_THROWN;
- }
+ JNU_ThrowIOExceptionWithLastError(env, "poll failed");
+ return JNI_FALSE;
}
}
--- a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java Wed Mar 20 13:54:50 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,8 @@
package sun.nio.ch;
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
/**
* Allows different platforms to call different native methods
--- a/src/java.base/windows/native/libnio/ch/Net.c Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/windows/native/libnio/ch/Net.c Wed Mar 20 13:54:50 2019 +0000
@@ -660,7 +660,7 @@
return rv;
}
-JNIEXPORT jint JNICALL
+JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_pollConnect(JNIEnv* env, jclass this, jobject fdo, jlong timeout)
{
int optError = 0;
@@ -684,13 +684,13 @@
if (result == SOCKET_ERROR) {
handleSocketError(env, WSAGetLastError());
- return IOS_THROWN;
+ return JNI_FALSE;
} else if (result == 0) {
- return 0;
+ return JNI_FALSE;
} else {
// connection established if writable and no error to check
if (FD_ISSET(fd, &wr) && !FD_ISSET(fd, &ex)) {
- return 1;
+ return JNI_TRUE;
}
result = getsockopt((SOCKET)fd,
SOL_SOCKET,
@@ -699,17 +699,13 @@
&n);
if (result == SOCKET_ERROR) {
int lastError = WSAGetLastError();
- if (lastError == WSAEINPROGRESS) {
- return IOS_UNAVAILABLE;
+ if (lastError != WSAEINPROGRESS) {
+ NET_ThrowNew(env, lastError, "getsockopt");
}
- NET_ThrowNew(env, lastError, "getsockopt");
- return IOS_THROWN;
+ } else if (optError != NO_ERROR) {
+ handleSocketError(env, optError);
}
- if (optError != NO_ERROR) {
- handleSocketError(env, optError);
- return IOS_THROWN;
- }
- return 0;
+ return JNI_FALSE;
}
}
--- a/src/java.base/windows/native/libnio/ch/SocketDispatcher.c Mon Mar 18 19:59:05 2019 +0000
+++ b/src/java.base/windows/native/libnio/ch/SocketDispatcher.c Wed Mar 20 13:54:50 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
return IOS_UNAVAILABLE;
}
if (theErr == WSAECONNRESET) {
- JNU_ThrowIOException(env, "Connection reset by peer");
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
} else {
JNU_ThrowIOExceptionWithLastError(env, "Read failed");
}
@@ -133,7 +133,7 @@
return IOS_UNAVAILABLE;
}
if (theErr == WSAECONNRESET) {
- JNU_ThrowIOException(env, "Connection reset by peer");
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
} else {
JNU_ThrowIOExceptionWithLastError(env, "Vector read failed");
}
--- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java Mon Mar 18 19:59:05 2019 +0000
+++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java Wed Mar 20 13:54:50 2019 +0000
@@ -465,7 +465,7 @@
if (state != ChannelState.PENDING)
throw new NoConnectionPendingException();
}
- int n = 0;
+ boolean connected = false;
try {
try {
begin();
@@ -477,26 +477,11 @@
receiverThread = NativeThread.current();
}
if (!isBlocking()) {
- for (;;) {
- n = Net.pollConnect(fd, 0);
- if ( (n == IOStatus.INTERRUPTED)
- && isOpen())
- continue;
- break;
- }
+ connected = Net.pollConnect(fd, 0);
} else {
- for (;;) {
- n = Net.pollConnect(fd, -1);
- if (n == 0) {
- // Loop in case of
- // spurious notifications
- continue;
- }
- if ( (n == IOStatus.INTERRUPTED)
- && isOpen())
- continue;
- break;
- }
+ do {
+ connected = Net.pollConnect(fd, -1);
+ } while (!connected && isOpen());
}
}
} finally {
@@ -504,16 +489,10 @@
receiverThread = 0;
if (state == ChannelState.KILLPENDING) {
kill();
- /* poll()/getsockopt() does not report
- * error (throws exception, with n = 0)
- * on Linux platform after dup2 and
- * signal-wakeup. Force n to 0 so the
- * end() can throw appropriate exception */
- n = 0;
+ connected = false;
}
}
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- assert IOStatus.check(n);
+ end(connected);
}
} catch (IOException x) {
/* If an exception was thrown, close the channel after
@@ -523,7 +502,7 @@
throw x;
}
- if (n > 0) {
+ if (connected) {
synchronized (stateLock) {
state = ChannelState.CONNECTED;
if (!isBound()) {