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. |