8233430: (sc) Socket adaptor restoring of blocking mode can override exception if socket closed
Reviewed-by: dfuchs, chegar
--- a/src/java.base/share/classes/sun/nio/ch/DummySocketImpl.java Sat Nov 02 10:02:18 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/DummySocketImpl.java Sun Nov 03 14:07:43 2019 +0000
@@ -31,8 +31,6 @@
import java.net.SocketAddress;
import java.net.SocketImpl;
import java.net.SocketOption;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.Set;
/**
@@ -41,12 +39,10 @@
*/
class DummySocketImpl extends SocketImpl {
- private static final PrivilegedAction<SocketImpl> NEW = DummySocketImpl::new;
-
private DummySocketImpl() { }
static SocketImpl create() {
- return AccessController.doPrivileged(NEW);
+ return new DummySocketImpl();
}
private static <T> T shouldNotGetHere() {
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Sat Nov 02 10:02:18 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Sun Nov 03 14:07:43 2019 +0000
@@ -332,8 +332,8 @@
n = Net.accept(fd, newfd, isaa);
}
} finally {
- // restore socket to blocking mode
- lockedConfigureBlocking(true);
+ // restore socket to blocking mode (if channel is open)
+ tryLockedConfigureBlocking(true);
}
} finally {
end(true, n > 0);
@@ -376,7 +376,7 @@
}
/**
- * Adjust the blocking mode while holding acceptLock.
+ * Adjust the blocking. acceptLock must already be held.
*/
private void lockedConfigureBlocking(boolean block) throws IOException {
assert acceptLock.isHeldByCurrentThread();
@@ -387,6 +387,25 @@
}
/**
+ * Adjusts the blocking mode if the channel is open. acceptLock must already
+ * be held.
+ *
+ * @return {@code true} if the blocking mode was adjusted, {@code false} if
+ * the blocking mode was not adjusted because the channel is closed
+ */
+ private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
+ assert acceptLock.isHeldByCurrentThread();
+ synchronized (stateLock) {
+ if (isOpen()) {
+ IOUtil.configureBlocking(fd, block);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
* Closes the socket if there are no accept in progress and the channel is
* not registered with a Selector.
*/
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Sat Nov 02 10:02:18 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Sun Nov 03 14:07:43 2019 +0000
@@ -573,7 +573,7 @@
}
/**
- * Adjust the blocking mode while holding the readLock or writeLock.
+ * Adjusts the blocking mode. readLock or writeLock must already be held.
*/
private void lockedConfigureBlocking(boolean block) throws IOException {
assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
@@ -584,6 +584,25 @@
}
/**
+ * Adjusts the blocking mode if the channel is open. readLock or writeLock
+ * must already be held.
+ *
+ * @return {@code true} if the blocking mode was adjusted, {@code false} if
+ * the blocking mode was not adjusted because the channel is closed
+ */
+ private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
+ assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
+ synchronized (stateLock) {
+ if (isOpen()) {
+ IOUtil.configureBlocking(fd, block);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
* Returns the local address, or null if not bound
*/
InetSocketAddress localAddress() {
@@ -1051,8 +1070,8 @@
int n = Net.connect(fd, isa.getAddress(), isa.getPort());
connected = (n > 0) ? true : finishTimedConnect(nanos);
} finally {
- // restore socket to blocking mode
- lockedConfigureBlocking(true);
+ // restore socket to blocking mode (if channel is open)
+ tryLockedConfigureBlocking(true);
}
} finally {
endConnect(true, connected);
@@ -1144,8 +1163,8 @@
try {
n = timedRead(b, off, len, nanos);
} finally {
- // restore socket to blocking mode
- lockedConfigureBlocking(true);
+ // restore socket to blocking mode (if channel is open)
+ tryLockedConfigureBlocking(true);
}
} else {
// read, no timeout