diff -r fd40b0b3d849 -r ffbb784a8873 src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Tue Feb 06 23:49:10 2018 +0530 +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Tue Feb 06 16:04:46 2018 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, 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 @@ -27,11 +27,30 @@ import java.io.FileDescriptor; import java.io.IOException; -import java.net.*; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketOption; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.nio.channels.spi.*; -import java.util.*; +import java.nio.channels.AlreadyBoundException; +import java.nio.channels.AlreadyConnectedException; +import java.nio.channels.AsynchronousCloseException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ConnectionPendingException; +import java.nio.channels.NoConnectionPendingException; +import java.nio.channels.NotYetConnectedException; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; + import sun.net.NetHooks; import sun.net.ext.ExtendedSocketOptions; @@ -59,10 +78,10 @@ private volatile long writerThread; // Lock held by current reading or connecting thread - private final Object readLock = new Object(); + private final ReentrantLock readLock = new ReentrantLock(); // Lock held by current writing or connecting thread - private final Object writeLock = new Object(); + private final ReentrantLock writeLock = new ReentrantLock(); // Lock held by any thread that modifies the state fields declared below // DO NOT invoke a blocking I/O operation while holding this lock! @@ -89,7 +108,6 @@ // Input/Output open private boolean isInputOpen = true; private boolean isOutputOpen = true; - private boolean readyToConnect = false; // Socket adaptor, created on demand private Socket socket; @@ -298,7 +316,8 @@ if (buf == null) throw new NullPointerException(); - synchronized (readLock) { + readLock.lock(); + try { if (!ensureReadOpen()) return -1; int n = 0; @@ -418,6 +437,8 @@ assert IOStatus.check(n); } + } finally { + readLock.unlock(); } } @@ -426,7 +447,8 @@ { if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) throw new IndexOutOfBoundsException(); - synchronized (readLock) { + readLock.lock(); + try { if (!ensureReadOpen()) return -1; long n = 0; @@ -453,13 +475,16 @@ } assert IOStatus.check(n); } + } finally { + readLock.unlock(); } } public int write(ByteBuffer buf) throws IOException { if (buf == null) throw new NullPointerException(); - synchronized (writeLock) { + writeLock.lock(); + try { ensureWriteOpen(); int n = 0; try { @@ -484,6 +509,8 @@ } assert IOStatus.check(n); } + } finally { + writeLock.unlock(); } } @@ -492,7 +519,8 @@ { if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) throw new IndexOutOfBoundsException(); - synchronized (writeLock) { + writeLock.lock(); + try { ensureWriteOpen(); long n = 0; try { @@ -517,12 +545,15 @@ } assert IOStatus.check(n); } + } finally { + writeLock.unlock(); } } // package-private int sendOutOfBandData(byte b) throws IOException { - synchronized (writeLock) { + writeLock.lock(); + try { ensureWriteOpen(); int n = 0; try { @@ -547,6 +578,8 @@ } assert IOStatus.check(n); } + } finally { + writeLock.unlock(); } } @@ -568,8 +601,10 @@ @Override public SocketChannel bind(SocketAddress local) throws IOException { - synchronized (readLock) { - synchronized (writeLock) { + readLock.lock(); + try { + writeLock.lock(); + try { synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); @@ -587,7 +622,11 @@ Net.bind(fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } + } finally { + writeLock.unlock(); } + } finally { + readLock.unlock(); } return this; } @@ -616,14 +655,16 @@ } public boolean connect(SocketAddress sa) throws IOException { - synchronized (readLock) { - synchronized (writeLock) { + readLock.lock(); + try { + writeLock.lock(); + try { ensureOpenAndUnconnected(); InetSocketAddress isa = Net.checkAddress(sa); SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), - isa.getPort()); + isa.getPort()); synchronized (blockingLock()) { int n = 0; try { @@ -636,8 +677,8 @@ // notify hook only if unbound if (localAddress == null) { NetHooks.beforeTcpConnect(fd, - isa.getAddress(), - isa.getPort()); + isa.getAddress(), + isa.getPort()); } readerThread = NativeThread.current(); } @@ -646,10 +687,9 @@ if (ia.isAnyLocalAddress()) ia = InetAddress.getLocalHost(); n = Net.connect(fd, - ia, - isa.getPort()); - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) + ia, + isa.getPort()); + if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; break; } @@ -686,13 +726,19 @@ } } return false; + } finally { + writeLock.unlock(); } + } finally { + readLock.unlock(); } } public boolean finishConnect() throws IOException { - synchronized (readLock) { - synchronized (writeLock) { + readLock.lock(); + try { + writeLock.lock(); + try { synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); @@ -714,24 +760,20 @@ } if (!isBlocking()) { for (;;) { - n = checkConnect(fd, false, - readyToConnect); - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) + n = checkConnect(fd, false); + if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; break; } } else { for (;;) { - n = checkConnect(fd, true, - readyToConnect); + n = checkConnect(fd, true); if (n == 0) { // Loop in case of // spurious notifications continue; } - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) + if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; break; } @@ -769,7 +811,11 @@ return true; } return false; + } finally { + writeLock.unlock(); } + } finally { + readLock.unlock(); } } @@ -903,9 +949,6 @@ if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) { newOps = intOps; sk.nioReadyOps(newOps); - // No need to poll again in checkConnect, - // the error will be detected there - readyToConnect = true; return (newOps & ~oldOps) != 0; } @@ -918,7 +961,6 @@ ((intOps & SelectionKey.OP_CONNECT) != 0) && ((state == ST_UNCONNECTED) || (state == ST_PENDING))) { newOps |= SelectionKey.OP_CONNECT; - readyToConnect = true; } if (((ops & Net.POLLOUT) != 0) && @@ -942,7 +984,8 @@ int poll(int events, long timeout) throws IOException { assert Thread.holdsLock(blockingLock()) && !isBlocking(); - synchronized (readLock) { + readLock.lock(); + try { int n = 0; try { begin(); @@ -957,6 +1000,8 @@ end(n > 0); } return n; + } finally { + readLock.unlock(); } } @@ -1024,8 +1069,7 @@ // -- Native methods -- - private static native int checkConnect(FileDescriptor fd, - boolean block, boolean ready) + private static native int checkConnect(FileDescriptor fd, boolean block) throws IOException; private static native int sendOutOfBandData(FileDescriptor fd, byte data)