< prev index next >

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

Print this page
@@ -101,10 +101,13 @@
      private boolean isReuseAddress;
  
      // Our socket adaptor, if any
      private ServerSocket socket;
  
+     // lazily set to true when the socket is configured non-blocking
+     private volatile boolean nonBlocking;
+ 
      // -- End of fields protected by stateLock
  
      ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
          this(sp, Net.isIPv6Available() ? INET6 : INET);
      }

@@ -386,10 +389,11 @@
          acceptLock.lock();
          try {
              boolean blocking = isBlocking();
              try {
                  begin(blocking);
+                 lockedConfigureNonBlockingIfNeeded();
                  n = implAccept(this.fd, newfd, saa);
                  if (blocking) {
                      while (IOStatus.okayToRetry(n) && isOpen()) {
                          park(Net.POLLIN);
                          n = implAccept(this.fd, newfd, saa);

@@ -512,39 +516,55 @@
              acceptLock.unlock();
          }
      }
  
      /**
-      * Adjust the blocking. acceptLock must already be held.
+      * Adjusts the blocking mode.
       */
      private void lockedConfigureBlocking(boolean block) throws IOException {
          assert acceptLock.isHeldByCurrentThread();
          synchronized (stateLock) {
              ensureOpen();
-             IOUtil.configureBlocking(fd, block);
+             // do nothing if virtual thread has forced the socket to be non-blocking
+             if (!nonBlocking) {
+                 IOUtil.configureBlocking(fd, block);
+             }
          }
      }
  
      /**
-      * 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
+      * Attempts to adjusts the blocking mode if the channel is open.
+      * @return {@code true} if the blocking mode was adjusted
       */
      private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
          assert acceptLock.isHeldByCurrentThread();
          synchronized (stateLock) {
-             if (isOpen()) {
+             // do nothing if virtual thread has forced the socket to be non-blocking
+             if (!nonBlocking && isOpen()) {
                  IOUtil.configureBlocking(fd, block);
                  return true;
              } else {
                  return false;
              }
          }
      }
  
+     /**
+      * Ensures that the socket is configured non-blocking when on a virtual
+      * thread.
+      */
+     private void lockedConfigureNonBlockingIfNeeded() throws IOException {
+         assert acceptLock.isHeldByCurrentThread();
+         if (!nonBlocking && (Thread.currentThread().isVirtual())) {
+             synchronized (stateLock) {
+                 ensureOpen();
+                 IOUtil.configureBlocking(fd, false);
+                 nonBlocking = true;
+             }
+         }
+     }
+ 
      /**
       * Closes the socket if there are no accept in progress and the channel is
       * not registered with a Selector.
       */
      private boolean tryClose() throws IOException {

@@ -581,12 +601,16 @@
              assert state < ST_CLOSING;
              state = ST_CLOSING;
              if (!tryClose()) {
                  long th = thread;
                  if (th != 0) {
-                     nd.preClose(fd);
-                     NativeThread.signal(th);
+                     if (NativeThread.isVirtualThread(th)) {
+                         Poller.stopPoll(fdVal);
+                     } else {
+                         nd.preClose(fd);
+                         NativeThread.signal(th);
+                     }
                  }
              }
          }
      }
  
< prev index next >