< prev index next >

src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java

Print this page

  98     private volatile boolean isInputClosed;
  99     private volatile boolean isOutputClosed;
 100 
 101     // Connection reset protected by readLock
 102     private boolean connectionReset;
 103 
 104     // -- The following fields are protected by stateLock
 105 
 106     // set true when exclusive binding is on and SO_REUSEADDR is emulated
 107     private boolean isReuseAddress;
 108 
 109     // State, increases monotonically
 110     private static final int ST_UNCONNECTED = 0;
 111     private static final int ST_CONNECTIONPENDING = 1;
 112     private static final int ST_CONNECTED = 2;
 113     private static final int ST_CLOSING = 3;
 114     private static final int ST_CLOSED = 4;
 115     private volatile int state;  // need stateLock to change
 116 
 117     // IDs of native threads doing reads and writes, for signalling
 118     private long readerThread;
 119     private long writerThread;
 120 
 121     // Binding
 122     private SocketAddress localAddress;
 123     private SocketAddress remoteAddress;
 124 
 125     // Socket adaptor, created on demand
 126     private Socket socket;
 127 
 128     // True if the channel's socket has been forced into non-blocking mode
 129     // by a virtual thread. It cannot be reset. When the channel is in
 130     // blocking mode and the channel's socket is in non-blocking mode then
 131     // operations that don't complete immediately will poll the socket and
 132     // preserve the semantics of blocking operations.
 133     private volatile boolean forcedNonBlocking;
 134 
 135     // -- End of fields protected by stateLock
 136 
 137     SocketChannelImpl(SelectorProvider sp) throws IOException {
 138         this(sp, Net.isIPv6Available() ? INET6 : INET);
 139     }

 368 
 369             synchronized (stateLock) {
 370                 ensureOpen();
 371                 // record thread so it can be signalled if needed
 372                 readerThread = NativeThread.current();
 373             }
 374         }
 375     }
 376 
 377     /**
 378      * Marks the end of a read operation that may have blocked.
 379      *
 380      * @throws AsynchronousCloseException if the channel was closed due to this
 381      * thread being interrupted on a blocking read operation.
 382      */
 383     private void endRead(boolean blocking, boolean completed)
 384         throws AsynchronousCloseException
 385     {
 386         if (blocking) {
 387             synchronized (stateLock) {
 388                 readerThread = 0;
 389                 if (state == ST_CLOSING) {
 390                     tryFinishClose();
 391                 }
 392             }
 393             // remove hook for Thread.interrupt
 394             end(completed);
 395         }
 396     }
 397 
 398     private void throwConnectionReset() throws SocketException {
 399         throw new SocketException("Connection reset");
 400     }
 401 
 402     private int implRead(ByteBuffer buf) throws IOException {
 403         Objects.requireNonNull(buf);
 404 
 405         readLock.lock();
 406         try {
 407             ensureOpenAndConnected();
 408             boolean blocking = isBlocking();

 522                 ensureOpen();
 523                 if (isOutputClosed)
 524                     throw new ClosedChannelException();
 525                 // record thread so it can be signalled if needed
 526                 writerThread = NativeThread.current();
 527             }
 528         }
 529     }
 530 
 531     /**
 532      * Marks the end of a write operation that may have blocked.
 533      *
 534      * @throws AsynchronousCloseException if the channel was closed due to this
 535      * thread being interrupted on a blocking write operation.
 536      */
 537     private void endWrite(boolean blocking, boolean completed)
 538         throws AsynchronousCloseException
 539     {
 540         if (blocking) {
 541             synchronized (stateLock) {
 542                 writerThread = 0;
 543                 if (state == ST_CLOSING) {
 544                     tryFinishClose();
 545                 }
 546             }
 547             // remove hook for Thread.interrupt
 548             end(completed);
 549         }
 550     }
 551 
 552     private int implWrite(ByteBuffer buf) throws IOException {
 553         Objects.requireNonNull(buf);
 554         writeLock.lock();
 555         try {
 556             ensureOpenAndConnected();
 557             boolean blocking = isBlocking();
 558             int n = 0;
 559             try {
 560                 beginWrite(blocking);
 561                 configureSocketNonBlockingIfVirtualThread();
 562                 n = IOUtil.write(fd, buf, -1, nd);

 673             synchronized (stateLock) {
 674                 ensureOpenAndConnected();
 675                 if (isOutputClosed)
 676                     throw new ClosedChannelException();
 677                 writerThread = NativeThread.current();
 678                 completed = true;
 679             }
 680         } finally {
 681             if (!completed) {
 682                 writeLock.unlock();
 683             }
 684         }
 685     }
 686 
 687     /**
 688      * Marks the end of a transfer to this channel.
 689      * @throws AsynchronousCloseException if not completed and the channel is closed
 690      */
 691     void afterTransferTo(boolean completed) throws AsynchronousCloseException {
 692         synchronized (stateLock) {
 693             writerThread = 0;
 694             if (state == ST_CLOSING) {
 695                 tryFinishClose();
 696             }
 697         }
 698         writeLock.unlock();
 699         if (!completed && !isOpen()) {
 700             throw new AsynchronousCloseException();
 701         }
 702     }
 703 
 704     @Override
 705     protected void implConfigureBlocking(boolean block) throws IOException {
 706         readLock.lock();
 707         try {
 708             writeLock.lock();
 709             try {
 710                 lockedConfigureBlocking(block);
 711             } finally {
 712                 writeLock.unlock();
 713             }

1058                     return connected;
1059                 } finally {
1060                     writeLock.unlock();
1061                 }
1062             } finally {
1063                 readLock.unlock();
1064             }
1065         } catch (IOException ioe) {
1066             // connect failed, close the channel
1067             close();
1068             throw Exceptions.ioException(ioe, remoteAddress);
1069         }
1070     }
1071 
1072     /**
1073      * Closes the socket if there are no I/O operations in progress (or no I/O
1074      * operations tracked), and the channel is not registered with a Selector.
1075      */
1076     private boolean tryClose() throws IOException {
1077         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
1078         if ((readerThread == 0) && (writerThread == 0) && !isRegistered()) {
1079             state = ST_CLOSED;
1080             nd.close(fd);
1081             return true;
1082         } else {
1083             return false;
1084         }
1085     }
1086 
1087     /**
1088      * Invokes tryClose to attempt to close the socket.
1089      *
1090      * This method is used for deferred closing by I/O and Selector operations.
1091      */
1092     private void tryFinishClose() {
1093         try {
1094             tryClose();
1095         } catch (IOException ignore) { }
1096     }
1097 
1098     /**

1201         // wait for any read/write operations to complete before trying to close
1202         readLock.lock();
1203         readLock.unlock();
1204         writeLock.lock();
1205         writeLock.unlock();
1206         synchronized (stateLock) {
1207             if (state == ST_CLOSING) {
1208                 tryFinishClose();
1209             }
1210         }
1211     }
1212 
1213     @Override
1214     public SocketChannel shutdownInput() throws IOException {
1215         synchronized (stateLock) {
1216             ensureOpen();
1217             if (!isConnected())
1218                 throw new NotYetConnectedException();
1219             if (!isInputClosed) {
1220                 Net.shutdown(fd, Net.SHUT_RD);
1221                 long reader = readerThread;
1222                 if (NativeThread.isVirtualThread(reader)) {
1223                     Poller.stopPoll(fdVal, Net.POLLIN);
1224                 } else if (NativeThread.isNativeThread(reader)) {
1225                     NativeThread.signal(reader);
1226                 }
1227                 isInputClosed = true;
1228             }
1229             return this;
1230         }
1231     }
1232 
1233     @Override
1234     public SocketChannel shutdownOutput() throws IOException {
1235         synchronized (stateLock) {
1236             ensureOpen();
1237             if (!isConnected())
1238                 throw new NotYetConnectedException();
1239             if (!isOutputClosed) {
1240                 Net.shutdown(fd, Net.SHUT_WR);
1241                 long writer = writerThread;
1242                 if (NativeThread.isVirtualThread(writer)) {
1243                     Poller.stopPoll(fdVal, Net.POLLOUT);
1244                 } else if (NativeThread.isNativeThread(writer)) {
1245                     NativeThread.signal(writer);
1246                 }
1247                 isOutputClosed = true;
1248             }
1249             return this;
1250         }
1251     }
1252 
1253     boolean isInputOpen() {
1254         return !isInputClosed;
1255     }
1256 
1257     boolean isOutputOpen() {
1258         return !isOutputClosed;
1259     }
1260 
1261     /**
1262      * Waits for a connection attempt to finish with a timeout
1263      * @throws SocketTimeoutException if the connect timeout elapses
1264      */
1265     private boolean finishTimedConnect(long nanos) throws IOException {

  98     private volatile boolean isInputClosed;
  99     private volatile boolean isOutputClosed;
 100 
 101     // Connection reset protected by readLock
 102     private boolean connectionReset;
 103 
 104     // -- The following fields are protected by stateLock
 105 
 106     // set true when exclusive binding is on and SO_REUSEADDR is emulated
 107     private boolean isReuseAddress;
 108 
 109     // State, increases monotonically
 110     private static final int ST_UNCONNECTED = 0;
 111     private static final int ST_CONNECTIONPENDING = 1;
 112     private static final int ST_CONNECTED = 2;
 113     private static final int ST_CLOSING = 3;
 114     private static final int ST_CLOSED = 4;
 115     private volatile int state;  // need stateLock to change
 116 
 117     // IDs of native threads doing reads and writes, for signalling
 118     private NativeThread readerThread;
 119     private NativeThread writerThread;
 120 
 121     // Binding
 122     private SocketAddress localAddress;
 123     private SocketAddress remoteAddress;
 124 
 125     // Socket adaptor, created on demand
 126     private Socket socket;
 127 
 128     // True if the channel's socket has been forced into non-blocking mode
 129     // by a virtual thread. It cannot be reset. When the channel is in
 130     // blocking mode and the channel's socket is in non-blocking mode then
 131     // operations that don't complete immediately will poll the socket and
 132     // preserve the semantics of blocking operations.
 133     private volatile boolean forcedNonBlocking;
 134 
 135     // -- End of fields protected by stateLock
 136 
 137     SocketChannelImpl(SelectorProvider sp) throws IOException {
 138         this(sp, Net.isIPv6Available() ? INET6 : INET);
 139     }

 368 
 369             synchronized (stateLock) {
 370                 ensureOpen();
 371                 // record thread so it can be signalled if needed
 372                 readerThread = NativeThread.current();
 373             }
 374         }
 375     }
 376 
 377     /**
 378      * Marks the end of a read operation that may have blocked.
 379      *
 380      * @throws AsynchronousCloseException if the channel was closed due to this
 381      * thread being interrupted on a blocking read operation.
 382      */
 383     private void endRead(boolean blocking, boolean completed)
 384         throws AsynchronousCloseException
 385     {
 386         if (blocking) {
 387             synchronized (stateLock) {
 388                 readerThread = null;
 389                 if (state == ST_CLOSING) {
 390                     tryFinishClose();
 391                 }
 392             }
 393             // remove hook for Thread.interrupt
 394             end(completed);
 395         }
 396     }
 397 
 398     private void throwConnectionReset() throws SocketException {
 399         throw new SocketException("Connection reset");
 400     }
 401 
 402     private int implRead(ByteBuffer buf) throws IOException {
 403         Objects.requireNonNull(buf);
 404 
 405         readLock.lock();
 406         try {
 407             ensureOpenAndConnected();
 408             boolean blocking = isBlocking();

 522                 ensureOpen();
 523                 if (isOutputClosed)
 524                     throw new ClosedChannelException();
 525                 // record thread so it can be signalled if needed
 526                 writerThread = NativeThread.current();
 527             }
 528         }
 529     }
 530 
 531     /**
 532      * Marks the end of a write operation that may have blocked.
 533      *
 534      * @throws AsynchronousCloseException if the channel was closed due to this
 535      * thread being interrupted on a blocking write operation.
 536      */
 537     private void endWrite(boolean blocking, boolean completed)
 538         throws AsynchronousCloseException
 539     {
 540         if (blocking) {
 541             synchronized (stateLock) {
 542                 writerThread = null;
 543                 if (state == ST_CLOSING) {
 544                     tryFinishClose();
 545                 }
 546             }
 547             // remove hook for Thread.interrupt
 548             end(completed);
 549         }
 550     }
 551 
 552     private int implWrite(ByteBuffer buf) throws IOException {
 553         Objects.requireNonNull(buf);
 554         writeLock.lock();
 555         try {
 556             ensureOpenAndConnected();
 557             boolean blocking = isBlocking();
 558             int n = 0;
 559             try {
 560                 beginWrite(blocking);
 561                 configureSocketNonBlockingIfVirtualThread();
 562                 n = IOUtil.write(fd, buf, -1, nd);

 673             synchronized (stateLock) {
 674                 ensureOpenAndConnected();
 675                 if (isOutputClosed)
 676                     throw new ClosedChannelException();
 677                 writerThread = NativeThread.current();
 678                 completed = true;
 679             }
 680         } finally {
 681             if (!completed) {
 682                 writeLock.unlock();
 683             }
 684         }
 685     }
 686 
 687     /**
 688      * Marks the end of a transfer to this channel.
 689      * @throws AsynchronousCloseException if not completed and the channel is closed
 690      */
 691     void afterTransferTo(boolean completed) throws AsynchronousCloseException {
 692         synchronized (stateLock) {
 693             writerThread = null;
 694             if (state == ST_CLOSING) {
 695                 tryFinishClose();
 696             }
 697         }
 698         writeLock.unlock();
 699         if (!completed && !isOpen()) {
 700             throw new AsynchronousCloseException();
 701         }
 702     }
 703 
 704     @Override
 705     protected void implConfigureBlocking(boolean block) throws IOException {
 706         readLock.lock();
 707         try {
 708             writeLock.lock();
 709             try {
 710                 lockedConfigureBlocking(block);
 711             } finally {
 712                 writeLock.unlock();
 713             }

1058                     return connected;
1059                 } finally {
1060                     writeLock.unlock();
1061                 }
1062             } finally {
1063                 readLock.unlock();
1064             }
1065         } catch (IOException ioe) {
1066             // connect failed, close the channel
1067             close();
1068             throw Exceptions.ioException(ioe, remoteAddress);
1069         }
1070     }
1071 
1072     /**
1073      * Closes the socket if there are no I/O operations in progress (or no I/O
1074      * operations tracked), and the channel is not registered with a Selector.
1075      */
1076     private boolean tryClose() throws IOException {
1077         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
1078         if ((readerThread == null) && (writerThread == null) && !isRegistered()) {
1079             state = ST_CLOSED;
1080             nd.close(fd);
1081             return true;
1082         } else {
1083             return false;
1084         }
1085     }
1086 
1087     /**
1088      * Invokes tryClose to attempt to close the socket.
1089      *
1090      * This method is used for deferred closing by I/O and Selector operations.
1091      */
1092     private void tryFinishClose() {
1093         try {
1094             tryClose();
1095         } catch (IOException ignore) { }
1096     }
1097 
1098     /**

1201         // wait for any read/write operations to complete before trying to close
1202         readLock.lock();
1203         readLock.unlock();
1204         writeLock.lock();
1205         writeLock.unlock();
1206         synchronized (stateLock) {
1207             if (state == ST_CLOSING) {
1208                 tryFinishClose();
1209             }
1210         }
1211     }
1212 
1213     @Override
1214     public SocketChannel shutdownInput() throws IOException {
1215         synchronized (stateLock) {
1216             ensureOpen();
1217             if (!isConnected())
1218                 throw new NotYetConnectedException();
1219             if (!isInputClosed) {
1220                 Net.shutdown(fd, Net.SHUT_RD);
1221                 if (NativeThread.isVirtualThread(readerThread)) {
1222                     Poller.stopPoll(readerThread.thread());



1223                 }
1224                 isInputClosed = true;
1225             }
1226             return this;
1227         }
1228     }
1229 
1230     @Override
1231     public SocketChannel shutdownOutput() throws IOException {
1232         synchronized (stateLock) {
1233             ensureOpen();
1234             if (!isConnected())
1235                 throw new NotYetConnectedException();
1236             if (!isOutputClosed) {
1237                 Net.shutdown(fd, Net.SHUT_WR);
1238                 if (NativeThread.isVirtualThread(writerThread)) {
1239                     Poller.stopPoll(writerThread.thread());



1240                 }
1241                 isOutputClosed = true;
1242             }
1243             return this;
1244         }
1245     }
1246 
1247     boolean isInputOpen() {
1248         return !isInputClosed;
1249     }
1250 
1251     boolean isOutputOpen() {
1252         return !isOutputClosed;
1253     }
1254 
1255     /**
1256      * Waits for a connection attempt to finish with a timeout
1257      * @throws SocketTimeoutException if the connect timeout elapses
1258      */
1259     private boolean finishTimedConnect(long nanos) throws IOException {
< prev index next >