src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
changeset 58808 9261ad32cba9
parent 55102 59567035d279
equal deleted inserted replaced
58805:d3382812b788 58808:9261ad32cba9
    28 import java.io.FileDescriptor;
    28 import java.io.FileDescriptor;
    29 import java.io.IOException;
    29 import java.io.IOException;
    30 import java.io.InputStream;
    30 import java.io.InputStream;
    31 import java.io.OutputStream;
    31 import java.io.OutputStream;
    32 import java.io.UncheckedIOException;
    32 import java.io.UncheckedIOException;
    33 import java.lang.invoke.MethodHandles;
    33 import java.lang.ref.Cleaner.Cleanable;
    34 import java.lang.invoke.VarHandle;
       
    35 import java.net.InetAddress;
    34 import java.net.InetAddress;
    36 import java.net.InetSocketAddress;
    35 import java.net.InetSocketAddress;
    37 import java.net.ProtocolFamily;
    36 import java.net.ProtocolFamily;
    38 import java.net.SocketAddress;
    37 import java.net.SocketAddress;
    39 import java.net.SocketException;
    38 import java.net.SocketException;
   104     private static final int ST_CLOSED = 5;
   103     private static final int ST_CLOSED = 5;
   105     private volatile int state;  // need stateLock to change
   104     private volatile int state;  // need stateLock to change
   106 
   105 
   107     // set by SocketImpl.create, protected by stateLock
   106     // set by SocketImpl.create, protected by stateLock
   108     private boolean stream;
   107     private boolean stream;
   109     private FileDescriptorCloser closer;
   108     private Cleanable cleaner;
   110 
   109 
   111     // set to true when the socket is in non-blocking mode
   110     // set to true when the socket is in non-blocking mode
   112     private volatile boolean nonBlocking;
   111     private volatile boolean nonBlocking;
   113 
   112 
   114     // used by connect/read/write/accept, protected by stateLock
   113     // used by connect/read/write/accept, protected by stateLock
   469             } catch (IOException ioe) {
   468             } catch (IOException ioe) {
   470                 if (!stream)
   469                 if (!stream)
   471                     ResourceManager.afterUdpClose();
   470                     ResourceManager.afterUdpClose();
   472                 throw ioe;
   471                 throw ioe;
   473             }
   472             }
       
   473             Runnable closer = closerFor(fd, stream);
   474             this.fd = fd;
   474             this.fd = fd;
   475             this.stream = stream;
   475             this.stream = stream;
   476             this.closer = FileDescriptorCloser.create(this);
   476             this.cleaner = CleanerFactory.cleaner().register(this, closer);
   477             this.state = ST_UNCONNECTED;
   477             this.state = ST_UNCONNECTED;
   478         }
   478         }
   479     }
   479     }
   480 
   480 
   481     /**
   481     /**
   775             nd.close(newfd);
   775             nd.close(newfd);
   776             throw ioe;
   776             throw ioe;
   777         }
   777         }
   778 
   778 
   779         // set the fields
   779         // set the fields
       
   780         Runnable closer = closerFor(newfd, true);
   780         synchronized (nsi.stateLock) {
   781         synchronized (nsi.stateLock) {
   781             nsi.fd = newfd;
   782             nsi.fd = newfd;
   782             nsi.stream = true;
   783             nsi.stream = true;
   783             nsi.closer = FileDescriptorCloser.create(nsi);
   784             nsi.cleaner = CleanerFactory.cleaner().register(nsi, closer);
   784             nsi.localport = localAddress.getPort();
   785             nsi.localport = localAddress.getPort();
   785             nsi.address = isaa[0].getAddress();
   786             nsi.address = isaa[0].getAddress();
   786             nsi.port = isaa[0].getPort();
   787             nsi.port = isaa[0].getPort();
   787             nsi.state = ST_CONNECTED;
   788             nsi.state = ST_CONNECTED;
   788         }
   789         }
   848      */
   849      */
   849     private boolean tryClose() throws IOException {
   850     private boolean tryClose() throws IOException {
   850         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
   851         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
   851         if (readerThread == 0 && writerThread == 0) {
   852         if (readerThread == 0 && writerThread == 0) {
   852             try {
   853             try {
   853                 closer.run();
   854                 cleaner.clean();
   854             } catch (UncheckedIOException ioe) {
   855             } catch (UncheckedIOException ioe) {
   855                 throw ioe.getCause();
   856                 throw ioe.getCause();
   856             } finally {
   857             } finally {
   857                 state = ST_CLOSED;
   858                 state = ST_CLOSED;
   858             }
   859             }
  1191             writeLock.unlock();
  1192             writeLock.unlock();
  1192         }
  1193         }
  1193     }
  1194     }
  1194 
  1195 
  1195     /**
  1196     /**
  1196      * A task that closes a SocketImpl's file descriptor. The task runs when the
  1197      * Returns an action to close the given file descriptor.
  1197      * SocketImpl is explicitly closed and when the SocketImpl becomes phantom
  1198      */
  1198      * reachable.
  1199     private static Runnable closerFor(FileDescriptor fd, boolean stream) {
  1199      */
  1200         if (stream) {
  1200     private static class FileDescriptorCloser implements Runnable {
  1201             return () -> {
  1201         private static final VarHandle CLOSED;
  1202                 try {
  1202         static {
  1203                     nd.close(fd);
  1203             try {
  1204                 } catch (IOException ioe) {
  1204                 MethodHandles.Lookup l = MethodHandles.lookup();
  1205                     throw new UncheckedIOException(ioe);
  1205                 CLOSED = l.findVarHandle(FileDescriptorCloser.class,
  1206                 }
  1206                                          "closed",
  1207             };
  1207                                          boolean.class);
  1208         } else {
  1208             } catch (Exception e) {
  1209             return () -> {
  1209                 throw new InternalError(e);
       
  1210             }
       
  1211         }
       
  1212 
       
  1213         private final FileDescriptor fd;
       
  1214         private final boolean stream;
       
  1215         private volatile boolean closed;
       
  1216 
       
  1217         FileDescriptorCloser(FileDescriptor fd, boolean stream) {
       
  1218             this.fd = fd;
       
  1219             this.stream = stream;
       
  1220         }
       
  1221 
       
  1222         static FileDescriptorCloser create(NioSocketImpl impl) {
       
  1223             assert Thread.holdsLock(impl.stateLock);
       
  1224             var closer = new FileDescriptorCloser(impl.fd, impl.stream);
       
  1225             CleanerFactory.cleaner().register(impl, closer);
       
  1226             return closer;
       
  1227         }
       
  1228 
       
  1229         @Override
       
  1230         public void run() {
       
  1231             if (CLOSED.compareAndSet(this, false, true)) {
       
  1232                 try {
  1210                 try {
  1233                     nd.close(fd);
  1211                     nd.close(fd);
  1234                 } catch (IOException ioe) {
  1212                 } catch (IOException ioe) {
  1235                     throw new UncheckedIOException(ioe);
  1213                     throw new UncheckedIOException(ioe);
  1236                 } finally {
  1214                 } finally {
  1237                     if (!stream) {
  1215                     // decrement
  1238                         // decrement
  1216                     ResourceManager.afterUdpClose();
  1239                         ResourceManager.afterUdpClose();
  1217                 }
  1240                     }
  1218             };
  1241                 }
       
  1242             }
       
  1243         }
  1219         }
  1244     }
  1220     }
  1245 
  1221 
  1246     /**
  1222     /**
  1247      * Attempts to acquire the given lock within the given waiting time.
  1223      * Attempts to acquire the given lock within the given waiting time.