src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
changeset 49001 ce06058197a4
parent 48761 74c1fa26435a
child 49290 07779973cbe2
equal deleted inserted replaced
49000:a406a9c451a0 49001:ce06058197a4
    33 import java.net.SocketAddress;
    33 import java.net.SocketAddress;
    34 import java.net.SocketOption;
    34 import java.net.SocketOption;
    35 import java.net.StandardProtocolFamily;
    35 import java.net.StandardProtocolFamily;
    36 import java.net.StandardSocketOptions;
    36 import java.net.StandardSocketOptions;
    37 import java.nio.channels.AlreadyBoundException;
    37 import java.nio.channels.AlreadyBoundException;
       
    38 import java.nio.channels.AsynchronousCloseException;
    38 import java.nio.channels.ClosedChannelException;
    39 import java.nio.channels.ClosedChannelException;
    39 import java.nio.channels.NotYetBoundException;
    40 import java.nio.channels.NotYetBoundException;
    40 import java.nio.channels.SelectionKey;
    41 import java.nio.channels.SelectionKey;
    41 import java.nio.channels.ServerSocketChannel;
    42 import java.nio.channels.ServerSocketChannel;
    42 import java.nio.channels.SocketChannel;
    43 import java.nio.channels.SocketChannel;
    43 import java.nio.channels.spi.SelectorProvider;
    44 import java.nio.channels.spi.SelectorProvider;
    44 import java.util.Collections;
    45 import java.util.Collections;
    45 import java.util.HashSet;
    46 import java.util.HashSet;
       
    47 import java.util.Objects;
    46 import java.util.Set;
    48 import java.util.Set;
    47 import java.util.concurrent.locks.ReentrantLock;
    49 import java.util.concurrent.locks.ReentrantLock;
    48 
    50 
    49 import sun.net.NetHooks;
    51 import sun.net.NetHooks;
    50 
    52 
    54 
    56 
    55 class ServerSocketChannelImpl
    57 class ServerSocketChannelImpl
    56     extends ServerSocketChannel
    58     extends ServerSocketChannel
    57     implements SelChImpl
    59     implements SelChImpl
    58 {
    60 {
    59 
       
    60     // Used to make native close and configure calls
    61     // Used to make native close and configure calls
    61     private static NativeDispatcher nd;
    62     private static NativeDispatcher nd;
    62 
    63 
    63     // Our file descriptor
    64     // Our file descriptor
    64     private final FileDescriptor fd;
    65     private final FileDescriptor fd;
    65     private final int fdVal;
    66     private final int fdVal;
    66 
    67 
    67     // ID of native thread currently blocked in this channel, for signalling
    68     // Lock held by thread currently blocked on this channel
    68     private volatile long thread;
       
    69 
       
    70     // Lock held by thread currently blocked in this channel
       
    71     private final ReentrantLock acceptLock = new ReentrantLock();
    69     private final ReentrantLock acceptLock = new ReentrantLock();
    72 
    70 
    73     // Lock held by any thread that modifies the state fields declared below
    71     // Lock held by any thread that modifies the state fields declared below
    74     // DO NOT invoke a blocking I/O operation while holding this lock!
    72     // DO NOT invoke a blocking I/O operation while holding this lock!
    75     private final Object stateLock = new Object();
    73     private final Object stateLock = new Object();
    76 
    74 
    77     // -- The following fields are protected by stateLock
    75     // -- The following fields are protected by stateLock
    78 
    76 
    79     // Channel state, increases monotonically
    77     // Channel state, increases monotonically
    80     private static final int ST_UNINITIALIZED = -1;
       
    81     private static final int ST_INUSE = 0;
    78     private static final int ST_INUSE = 0;
    82     private static final int ST_KILLED = 1;
    79     private static final int ST_CLOSING = 1;
    83     private int state = ST_UNINITIALIZED;
    80     private static final int ST_KILLPENDING = 2;
       
    81     private static final int ST_KILLED = 3;
       
    82     private int state;
       
    83 
       
    84     // ID of native thread currently blocked in this channel, for signalling
       
    85     private long thread;
    84 
    86 
    85     // Binding
    87     // Binding
    86     private InetSocketAddress localAddress; // null => unbound
    88     private InetSocketAddress localAddress; // null => unbound
    87 
    89 
    88     // set true when exclusive binding is on and SO_REUSEADDR is emulated
    90     // set true when exclusive binding is on and SO_REUSEADDR is emulated
    96 
    98 
    97     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
    99     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
    98         super(sp);
   100         super(sp);
    99         this.fd =  Net.serverSocket(true);
   101         this.fd =  Net.serverSocket(true);
   100         this.fdVal = IOUtil.fdVal(fd);
   102         this.fdVal = IOUtil.fdVal(fd);
   101         this.state = ST_INUSE;
   103     }
   102     }
   104 
   103 
   105     ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
   104     ServerSocketChannelImpl(SelectorProvider sp,
       
   105                             FileDescriptor fd,
       
   106                             boolean bound)
       
   107         throws IOException
   106         throws IOException
   108     {
   107     {
   109         super(sp);
   108         super(sp);
   110         this.fd =  fd;
   109         this.fd =  fd;
   111         this.fdVal = IOUtil.fdVal(fd);
   110         this.fdVal = IOUtil.fdVal(fd);
   112         this.state = ST_INUSE;
   111         if (bound) {
   113         if (bound)
   112             synchronized (stateLock) {
   114             localAddress = Net.localAddress(fd);
   113                 localAddress = Net.localAddress(fd);
   115     }
   114             }
   116 
   115         }
       
   116     }
       
   117 
       
   118     // @throws ClosedChannelException if channel is closed
       
   119     private void ensureOpen() throws ClosedChannelException {
       
   120         if (!isOpen())
       
   121             throw new ClosedChannelException();
       
   122     }
       
   123 
       
   124     @Override
   117     public ServerSocket socket() {
   125     public ServerSocket socket() {
   118         synchronized (stateLock) {
   126         synchronized (stateLock) {
   119             if (socket == null)
   127             if (socket == null)
   120                 socket = ServerSocketAdaptor.create(this);
   128                 socket = ServerSocketAdaptor.create(this);
   121             return socket;
   129             return socket;
   123     }
   131     }
   124 
   132 
   125     @Override
   133     @Override
   126     public SocketAddress getLocalAddress() throws IOException {
   134     public SocketAddress getLocalAddress() throws IOException {
   127         synchronized (stateLock) {
   135         synchronized (stateLock) {
   128             if (!isOpen())
   136             ensureOpen();
   129                 throw new ClosedChannelException();
   137             return (localAddress == null)
   130             return localAddress == null ? localAddress
   138                     ? null
   131                     : Net.getRevealedLocalAddress(
   139                     : Net.getRevealedLocalAddress(localAddress);
   132                           Net.asInetSocketAddress(localAddress));
       
   133         }
   140         }
   134     }
   141     }
   135 
   142 
   136     @Override
   143     @Override
   137     public <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
   144     public <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
   138         throws IOException
   145         throws IOException
   139     {
   146     {
   140         if (name == null)
   147         Objects.requireNonNull(name);
   141             throw new NullPointerException();
       
   142         if (!supportedOptions().contains(name))
   148         if (!supportedOptions().contains(name))
   143             throw new UnsupportedOperationException("'" + name + "' not supported");
   149             throw new UnsupportedOperationException("'" + name + "' not supported");
   144         synchronized (stateLock) {
   150         synchronized (stateLock) {
   145             if (!isOpen())
   151             ensureOpen();
   146                 throw new ClosedChannelException();
       
   147 
   152 
   148             if (name == StandardSocketOptions.IP_TOS) {
   153             if (name == StandardSocketOptions.IP_TOS) {
   149                 ProtocolFamily family = Net.isIPv6Available() ?
   154                 ProtocolFamily family = Net.isIPv6Available() ?
   150                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
   155                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
   151                 Net.setSocketOption(fd, family, name, value);
   156                 Net.setSocketOption(fd, family, name, value);
   152                 return this;
   157                 return this;
   153             }
   158             }
   154 
   159 
   155             if (name == StandardSocketOptions.SO_REUSEADDR &&
   160             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
   156                     Net.useExclusiveBind())
       
   157             {
       
   158                 // SO_REUSEADDR emulated when using exclusive bind
   161                 // SO_REUSEADDR emulated when using exclusive bind
   159                 isReuseAddress = (Boolean)value;
   162                 isReuseAddress = (Boolean)value;
   160             } else {
   163             } else {
   161                 // no options that require special handling
   164                 // no options that require special handling
   162                 Net.setSocketOption(fd, Net.UNSPEC, name, value);
   165                 Net.setSocketOption(fd, Net.UNSPEC, name, value);
   168     @Override
   171     @Override
   169     @SuppressWarnings("unchecked")
   172     @SuppressWarnings("unchecked")
   170     public <T> T getOption(SocketOption<T> name)
   173     public <T> T getOption(SocketOption<T> name)
   171         throws IOException
   174         throws IOException
   172     {
   175     {
   173         if (name == null)
   176         Objects.requireNonNull(name);
   174             throw new NullPointerException();
       
   175         if (!supportedOptions().contains(name))
   177         if (!supportedOptions().contains(name))
   176             throw new UnsupportedOperationException("'" + name + "' not supported");
   178             throw new UnsupportedOperationException("'" + name + "' not supported");
   177 
   179 
   178         synchronized (stateLock) {
   180         synchronized (stateLock) {
   179             if (!isOpen())
   181             ensureOpen();
   180                 throw new ClosedChannelException();
   182             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
   181             if (name == StandardSocketOptions.SO_REUSEADDR &&
       
   182                     Net.useExclusiveBind())
       
   183             {
       
   184                 // SO_REUSEADDR emulated when using exclusive bind
   183                 // SO_REUSEADDR emulated when using exclusive bind
   185                 return (T)Boolean.valueOf(isReuseAddress);
   184                 return (T)Boolean.valueOf(isReuseAddress);
   186             }
   185             }
   187             // no options that require special handling
   186             // no options that require special handling
   188             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
   187             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
   191 
   190 
   192     private static class DefaultOptionsHolder {
   191     private static class DefaultOptionsHolder {
   193         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
   192         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
   194 
   193 
   195         private static Set<SocketOption<?>> defaultOptions() {
   194         private static Set<SocketOption<?>> defaultOptions() {
   196             HashSet<SocketOption<?>> set = new HashSet<>(2);
   195             HashSet<SocketOption<?>> set = new HashSet<>();
   197             set.add(StandardSocketOptions.SO_RCVBUF);
   196             set.add(StandardSocketOptions.SO_RCVBUF);
   198             set.add(StandardSocketOptions.SO_REUSEADDR);
   197             set.add(StandardSocketOptions.SO_REUSEADDR);
   199             if (Net.isReusePortAvailable()) {
   198             if (Net.isReusePortAvailable()) {
   200                 set.add(StandardSocketOptions.SO_REUSEPORT);
   199                 set.add(StandardSocketOptions.SO_REUSEPORT);
   201             }
   200             }
   207     @Override
   206     @Override
   208     public final Set<SocketOption<?>> supportedOptions() {
   207     public final Set<SocketOption<?>> supportedOptions() {
   209         return DefaultOptionsHolder.defaultOptions;
   208         return DefaultOptionsHolder.defaultOptions;
   210     }
   209     }
   211 
   210 
   212     public boolean isBound() {
       
   213         synchronized (stateLock) {
       
   214             return localAddress != null;
       
   215         }
       
   216     }
       
   217 
       
   218     public InetSocketAddress localAddress() {
       
   219         synchronized (stateLock) {
       
   220             return localAddress;
       
   221         }
       
   222     }
       
   223 
       
   224     @Override
   211     @Override
   225     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
   212     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
   226         acceptLock.lock();
   213         acceptLock.lock();
   227         try {
   214         try {
   228             if (!isOpen())
       
   229                 throw new ClosedChannelException();
       
   230             if (isBound())
       
   231                 throw new AlreadyBoundException();
       
   232             InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
       
   233                 Net.checkAddress(local);
       
   234             SecurityManager sm = System.getSecurityManager();
       
   235             if (sm != null)
       
   236                 sm.checkListen(isa.getPort());
       
   237             NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
       
   238             Net.bind(fd, isa.getAddress(), isa.getPort());
       
   239             Net.listen(fd, backlog < 1 ? 50 : backlog);
       
   240             synchronized (stateLock) {
   215             synchronized (stateLock) {
       
   216                 ensureOpen();
       
   217                 if (localAddress != null)
       
   218                     throw new AlreadyBoundException();
       
   219                 InetSocketAddress isa = (local == null)
       
   220                                         ? new InetSocketAddress(0)
       
   221                                         : Net.checkAddress(local);
       
   222                 SecurityManager sm = System.getSecurityManager();
       
   223                 if (sm != null)
       
   224                     sm.checkListen(isa.getPort());
       
   225                 NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
       
   226                 Net.bind(fd, isa.getAddress(), isa.getPort());
       
   227                 Net.listen(fd, backlog < 1 ? 50 : backlog);
   241                 localAddress = Net.localAddress(fd);
   228                 localAddress = Net.localAddress(fd);
   242             }
   229             }
   243         } finally {
   230         } finally {
   244             acceptLock.unlock();
   231             acceptLock.unlock();
   245         }
   232         }
   246         return this;
   233         return this;
   247     }
   234     }
   248 
   235 
       
   236     /**
       
   237      * Marks the beginning of an I/O operation that might block.
       
   238      *
       
   239      * @throws ClosedChannelException if the channel is closed
       
   240      * @throws NotYetBoundException if the channel's socket has not been bound yet
       
   241      */
       
   242     private void begin(boolean blocking) throws ClosedChannelException {
       
   243         if (blocking)
       
   244             begin();  // set blocker to close channel if interrupted
       
   245         synchronized (stateLock) {
       
   246             ensureOpen();
       
   247             if (localAddress == null)
       
   248                 throw new NotYetBoundException();
       
   249             if (blocking)
       
   250                 thread = NativeThread.current();
       
   251         }
       
   252     }
       
   253 
       
   254     /**
       
   255      * Marks the end of an I/O operation that may have blocked.
       
   256      *
       
   257      * @throws AsynchronousCloseException if the channel was closed due to this
       
   258      * thread being interrupted on a blocking I/O operation.
       
   259      */
       
   260     private void end(boolean blocking, boolean completed)
       
   261         throws AsynchronousCloseException
       
   262     {
       
   263         if (blocking) {
       
   264             synchronized (stateLock) {
       
   265                 thread = 0;
       
   266                 // notify any thread waiting in implCloseSelectableChannel
       
   267                 if (state == ST_CLOSING) {
       
   268                     stateLock.notifyAll();
       
   269                 }
       
   270             }
       
   271             end(completed);
       
   272         }
       
   273     }
       
   274 
       
   275     @Override
   249     public SocketChannel accept() throws IOException {
   276     public SocketChannel accept() throws IOException {
   250         acceptLock.lock();
   277         acceptLock.lock();
   251         try {
   278         try {
   252             if (!isOpen())
       
   253                 throw new ClosedChannelException();
       
   254             if (!isBound())
       
   255                 throw new NotYetBoundException();
       
   256             SocketChannel sc = null;
       
   257 
       
   258             int n = 0;
   279             int n = 0;
   259             FileDescriptor newfd = new FileDescriptor();
   280             FileDescriptor newfd = new FileDescriptor();
   260             InetSocketAddress[] isaa = new InetSocketAddress[1];
   281             InetSocketAddress[] isaa = new InetSocketAddress[1];
   261 
   282 
       
   283             boolean blocking = isBlocking();
   262             try {
   284             try {
   263                 begin();
   285                 begin(blocking);
   264                 if (!isOpen())
   286                 do {
   265                     return null;
       
   266                 thread = NativeThread.current();
       
   267                 for (;;) {
       
   268                     n = accept(this.fd, newfd, isaa);
   287                     n = accept(this.fd, newfd, isaa);
   269                     if ((n == IOStatus.INTERRUPTED) && isOpen())
   288                 } while (n == IOStatus.INTERRUPTED && isOpen());
   270                         continue;
       
   271                     break;
       
   272                 }
       
   273             } finally {
   289             } finally {
   274                 thread = 0;
   290                 end(blocking, n > 0);
   275                 end(n > 0);
       
   276                 assert IOStatus.check(n);
   291                 assert IOStatus.check(n);
   277             }
   292             }
   278 
   293 
   279             if (n < 1)
   294             if (n < 1)
   280                 return null;
   295                 return null;
   281 
   296 
       
   297             // newly accepted socket is initially in blocking mode
   282             IOUtil.configureBlocking(newfd, true);
   298             IOUtil.configureBlocking(newfd, true);
       
   299 
   283             InetSocketAddress isa = isaa[0];
   300             InetSocketAddress isa = isaa[0];
   284             sc = new SocketChannelImpl(provider(), newfd, isa);
   301             SocketChannel sc = new SocketChannelImpl(provider(), newfd, isa);
       
   302 
       
   303             // check permitted to accept connections from the remote address
   285             SecurityManager sm = System.getSecurityManager();
   304             SecurityManager sm = System.getSecurityManager();
   286             if (sm != null) {
   305             if (sm != null) {
   287                 try {
   306                 try {
   288                     sm.checkAccept(isa.getAddress().getHostAddress(),
   307                     sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
   289                                    isa.getPort());
       
   290                 } catch (SecurityException x) {
   308                 } catch (SecurityException x) {
   291                     sc.close();
   309                     sc.close();
   292                     throw x;
   310                     throw x;
   293                 }
   311                 }
   294             }
   312             }
   297         } finally {
   315         } finally {
   298             acceptLock.unlock();
   316             acceptLock.unlock();
   299         }
   317         }
   300     }
   318     }
   301 
   319 
       
   320     @Override
   302     protected void implConfigureBlocking(boolean block) throws IOException {
   321     protected void implConfigureBlocking(boolean block) throws IOException {
   303         IOUtil.configureBlocking(fd, block);
   322         acceptLock.lock();
   304     }
   323         try {
   305 
   324             synchronized (stateLock) {
       
   325                 ensureOpen();
       
   326                 IOUtil.configureBlocking(fd, block);
       
   327             }
       
   328         } finally {
       
   329             acceptLock.unlock();
       
   330         }
       
   331     }
       
   332 
       
   333     /**
       
   334      * Invoked by implCloseChannel to close the channel.
       
   335      *
       
   336      * This method waits for outstanding I/O operations to complete. When in
       
   337      * blocking mode, the socket is pre-closed and the threads in blocking I/O
       
   338      * operations are signalled to ensure that the outstanding I/O operations
       
   339      * complete quickly.
       
   340      *
       
   341      * The socket is closed by this method when it is not registered with a
       
   342      * Selector. Note that a channel configured blocking may be registered with
       
   343      * a Selector. This arises when a key is canceled and the channel configured
       
   344      * to blocking mode before the key is flushed from the Selector.
       
   345      */
       
   346     @Override
   306     protected void implCloseSelectableChannel() throws IOException {
   347     protected void implCloseSelectableChannel() throws IOException {
   307         synchronized (stateLock) {
   348         assert !isOpen();
   308             if (state != ST_KILLED)
   349 
   309                 nd.preClose(fd);
   350         boolean interrupted = false;
   310             long th = thread;
   351         boolean blocking;
   311             if (th != 0)
   352 
   312                 NativeThread.signal(th);
   353         // set state to ST_CLOSING
   313             if (!isRegistered())
   354         synchronized (stateLock) {
   314                 kill();
   355             assert state < ST_CLOSING;
   315         }
   356             state = ST_CLOSING;
   316     }
   357             blocking = isBlocking();
   317 
   358         }
       
   359 
       
   360         // wait for any outstanding accept to complete
       
   361         if (blocking) {
       
   362             synchronized (stateLock) {
       
   363                 assert state == ST_CLOSING;
       
   364                 long th = thread;
       
   365                 if (th != 0) {
       
   366                     nd.preClose(fd);
       
   367                     NativeThread.signal(th);
       
   368 
       
   369                     // wait for accept operation to end
       
   370                     while (thread != 0) {
       
   371                         try {
       
   372                             stateLock.wait();
       
   373                         } catch (InterruptedException e) {
       
   374                             interrupted = true;
       
   375                         }
       
   376                     }
       
   377                 }
       
   378             }
       
   379         } else {
       
   380             // non-blocking mode: wait for accept to complete
       
   381             acceptLock.lock();
       
   382             acceptLock.unlock();
       
   383         }
       
   384 
       
   385         // set state to ST_KILLPENDING
       
   386         synchronized (stateLock) {
       
   387             assert state == ST_CLOSING;
       
   388             state = ST_KILLPENDING;
       
   389         }
       
   390 
       
   391         // close socket if not registered with Selector
       
   392         if (!isRegistered())
       
   393             kill();
       
   394 
       
   395         // restore interrupt status
       
   396         if (interrupted)
       
   397             Thread.currentThread().interrupt();
       
   398     }
       
   399 
       
   400     @Override
   318     public void kill() throws IOException {
   401     public void kill() throws IOException {
   319         synchronized (stateLock) {
   402         synchronized (stateLock) {
   320             if (state == ST_KILLED)
   403             if (state == ST_KILLPENDING) {
   321                 return;
       
   322             if (state == ST_UNINITIALIZED) {
       
   323                 state = ST_KILLED;
   404                 state = ST_KILLED;
   324                 return;
   405                 nd.close(fd);
   325             }
   406             }
   326             assert !isOpen() && !isRegistered();
   407         }
   327             nd.close(fd);
   408     }
   328             state = ST_KILLED;
   409 
       
   410     /**
       
   411      * Returns true if channel's socket is bound
       
   412      */
       
   413     boolean isBound() {
       
   414         synchronized (stateLock) {
       
   415             return localAddress != null;
       
   416         }
       
   417     }
       
   418 
       
   419     /**
       
   420      * Returns the local address, or null if not bound
       
   421      */
       
   422     InetSocketAddress localAddress() {
       
   423         synchronized (stateLock) {
       
   424             return localAddress;
       
   425         }
       
   426     }
       
   427 
       
   428     /**
       
   429      * Poll this channel's socket for a new connection up to the given timeout.
       
   430      * @return {@code true} if there is a connection to accept
       
   431      */
       
   432     boolean pollAccept(long timeout) throws IOException {
       
   433         assert Thread.holdsLock(blockingLock()) && isBlocking();
       
   434         acceptLock.lock();
       
   435         try {
       
   436             boolean polled = false;
       
   437             try {
       
   438                 begin(true);
       
   439                 int n = Net.poll(fd, Net.POLLIN, timeout);
       
   440                 polled = (n > 0);
       
   441             } finally {
       
   442                 end(true, polled);
       
   443             }
       
   444             return polled;
       
   445         } finally {
       
   446             acceptLock.unlock();
   329         }
   447         }
   330     }
   448     }
   331 
   449 
   332     /**
   450     /**
   333      * Translates native poll revent set into a ready operation set
   451      * Translates native poll revent set into a ready operation set
   363         return translateReadyOps(ops, sk.nioReadyOps(), sk);
   481         return translateReadyOps(ops, sk.nioReadyOps(), sk);
   364     }
   482     }
   365 
   483 
   366     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
   484     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
   367         return translateReadyOps(ops, 0, sk);
   485         return translateReadyOps(ops, 0, sk);
   368     }
       
   369 
       
   370     // package-private
       
   371     int poll(int events, long timeout) throws IOException {
       
   372         assert Thread.holdsLock(blockingLock()) && !isBlocking();
       
   373 
       
   374         acceptLock.lock();
       
   375         try {
       
   376             int n = 0;
       
   377             try {
       
   378                 begin();
       
   379                 synchronized (stateLock) {
       
   380                     if (!isOpen())
       
   381                         return 0;
       
   382                     thread = NativeThread.current();
       
   383                 }
       
   384                 n = Net.poll(fd, events, timeout);
       
   385             } finally {
       
   386                 thread = 0;
       
   387                 end(n > 0);
       
   388             }
       
   389             return n;
       
   390         } finally {
       
   391             acceptLock.unlock();
       
   392         }
       
   393     }
   486     }
   394 
   487 
   395     /**
   488     /**
   396      * Translates an interest operation set into a native poll event set
   489      * Translates an interest operation set into a native poll event set
   397      */
   490      */
   419         sb.append('[');
   512         sb.append('[');
   420         if (!isOpen()) {
   513         if (!isOpen()) {
   421             sb.append("closed");
   514             sb.append("closed");
   422         } else {
   515         } else {
   423             synchronized (stateLock) {
   516             synchronized (stateLock) {
   424                 InetSocketAddress addr = localAddress();
   517                 InetSocketAddress addr = localAddress;
   425                 if (addr == null) {
   518                 if (addr == null) {
   426                     sb.append("unbound");
   519                     sb.append("unbound");
   427                 } else {
   520                 } else {
   428                     sb.append(Net.getRevealedLocalAddressAsString(addr));
   521                     sb.append(Net.getRevealedLocalAddressAsString(addr));
   429                 }
   522                 }
   436     /**
   529     /**
   437      * Accept a connection on a socket.
   530      * Accept a connection on a socket.
   438      *
   531      *
   439      * @implNote Wrap native call to allow instrumentation.
   532      * @implNote Wrap native call to allow instrumentation.
   440      */
   533      */
   441     private int accept(FileDescriptor ssfd, FileDescriptor newfd,
   534     private int accept(FileDescriptor ssfd,
       
   535                        FileDescriptor newfd,
   442                        InetSocketAddress[] isaa)
   536                        InetSocketAddress[] isaa)
   443         throws IOException
   537         throws IOException
   444     {
   538     {
   445         return accept0(ssfd, newfd, isaa);
   539         return accept0(ssfd, newfd, isaa);
   446     }
   540     }
   450     // Accepts a new connection, setting the given file descriptor to refer to
   544     // Accepts a new connection, setting the given file descriptor to refer to
   451     // the new socket and setting isaa[0] to the socket's remote address.
   545     // the new socket and setting isaa[0] to the socket's remote address.
   452     // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
   546     // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
   453     // connections are pending) or IOStatus.INTERRUPTED.
   547     // connections are pending) or IOStatus.INTERRUPTED.
   454     //
   548     //
   455     private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
   549     private native int accept0(FileDescriptor ssfd,
       
   550                                FileDescriptor newfd,
   456                                InetSocketAddress[] isaa)
   551                                InetSocketAddress[] isaa)
   457         throws IOException;
   552         throws IOException;
   458 
   553 
   459     private static native void initIDs();
   554     private static native void initIDs();
   460 
   555