8233430: (sc) Socket adaptor restoring of blocking mode can override exception if socket closed

Reviewed-by: dfuchs, chegar
This commit is contained in:
Alan Bateman 2019-11-03 14:07:43 +00:00
parent db4909bf99
commit fd077ea9ae
3 changed files with 47 additions and 13 deletions

View file

@ -31,8 +31,6 @@ import java.net.InetAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.SocketImpl; import java.net.SocketImpl;
import java.net.SocketOption; import java.net.SocketOption;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set; import java.util.Set;
/** /**
@ -41,12 +39,10 @@ import java.util.Set;
*/ */
class DummySocketImpl extends SocketImpl { class DummySocketImpl extends SocketImpl {
private static final PrivilegedAction<SocketImpl> NEW = DummySocketImpl::new;
private DummySocketImpl() { } private DummySocketImpl() { }
static SocketImpl create() { static SocketImpl create() {
return AccessController.doPrivileged(NEW); return new DummySocketImpl();
} }
private static <T> T shouldNotGetHere() { private static <T> T shouldNotGetHere() {

View file

@ -332,8 +332,8 @@ class ServerSocketChannelImpl
n = Net.accept(fd, newfd, isaa); n = Net.accept(fd, newfd, isaa);
} }
} finally { } finally {
// restore socket to blocking mode // restore socket to blocking mode (if channel is open)
lockedConfigureBlocking(true); tryLockedConfigureBlocking(true);
} }
} finally { } finally {
end(true, n > 0); end(true, n > 0);
@ -376,7 +376,7 @@ class ServerSocketChannelImpl
} }
/** /**
* Adjust the blocking mode while holding acceptLock. * Adjust the blocking. acceptLock must already be held.
*/ */
private void lockedConfigureBlocking(boolean block) throws IOException { private void lockedConfigureBlocking(boolean block) throws IOException {
assert acceptLock.isHeldByCurrentThread(); assert acceptLock.isHeldByCurrentThread();
@ -386,6 +386,25 @@ class ServerSocketChannelImpl
} }
} }
/**
* 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 * Closes the socket if there are no accept in progress and the channel is
* not registered with a Selector. * not registered with a Selector.

View file

@ -573,7 +573,7 @@ class SocketChannelImpl
} }
/** /**
* 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 { private void lockedConfigureBlocking(boolean block) throws IOException {
assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread(); assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
@ -583,6 +583,25 @@ class SocketChannelImpl
} }
} }
/**
* 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 * Returns the local address, or null if not bound
*/ */
@ -1051,8 +1070,8 @@ class SocketChannelImpl
int n = Net.connect(fd, isa.getAddress(), isa.getPort()); int n = Net.connect(fd, isa.getAddress(), isa.getPort());
connected = (n > 0) ? true : finishTimedConnect(nanos); connected = (n > 0) ? true : finishTimedConnect(nanos);
} finally { } finally {
// restore socket to blocking mode // restore socket to blocking mode (if channel is open)
lockedConfigureBlocking(true); tryLockedConfigureBlocking(true);
} }
} finally { } finally {
endConnect(true, connected); endConnect(true, connected);
@ -1144,8 +1163,8 @@ class SocketChannelImpl
try { try {
n = timedRead(b, off, len, nanos); n = timedRead(b, off, len, nanos);
} finally { } finally {
// restore socket to blocking mode // restore socket to blocking mode (if channel is open)
lockedConfigureBlocking(true); tryLockedConfigureBlocking(true);
} }
} else { } else {
// read, no timeout // read, no timeout