86
87 // Lock held when writing
88 private final ReentrantLock writeLock = new ReentrantLock();
89
90 // The stateLock for read/changing state
91 private final Object stateLock = new Object();
92 private static final int ST_NEW = 0;
93 private static final int ST_UNCONNECTED = 1;
94 private static final int ST_CONNECTING = 2;
95 private static final int ST_CONNECTED = 3;
96 private static final int ST_CLOSING = 4;
97 private static final int ST_CLOSED = 5;
98 private volatile int state; // need stateLock to change
99
100 private Cleanable cleaner;
101
102 // set to true when the socket is in non-blocking mode
103 private volatile boolean nonBlocking;
104
105 // used by connect/read/write/accept, protected by stateLock
106 private long readerThread;
107 private long writerThread;
108
109 // used when SO_REUSEADDR is emulated, protected by stateLock
110 private boolean isReuseAddress;
111
112 // read or accept timeout in millis
113 private volatile int timeout;
114
115 // flags to indicate if the connection is shutdown for input and output
116 private volatile boolean isInputClosed;
117 private volatile boolean isOutputClosed;
118
119 // used by read to emulate legacy behavior, protected by readLock
120 private boolean readEOF;
121 private boolean connectionReset;
122
123 /**
124 * Creates an instance of this SocketImpl.
125 * @param server true if this is a SocketImpl for a ServerSocket
126 */
127 public NioSocketImpl(boolean server) {
201 * @throws IOException if there is an I/O error changing the blocking mode
202 */
203 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
204 throws IOException
205 {
206 if (!nonBlocking
207 && (timed || Thread.currentThread().isVirtual())) {
208 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
209 IOUtil.configureBlocking(fd, false);
210 nonBlocking = true;
211 }
212 }
213
214 /**
215 * Marks the beginning of a read operation that might block.
216 * @throws SocketException if the socket is closed or not connected
217 */
218 private FileDescriptor beginRead() throws SocketException {
219 synchronized (stateLock) {
220 ensureOpenAndConnected();
221 readerThread = NativeThread.current();
222 return fd;
223 }
224 }
225
226 /**
227 * Marks the end of a read operation that may have blocked.
228 * @throws SocketException is the socket is closed
229 */
230 private void endRead(boolean completed) throws SocketException {
231 synchronized (stateLock) {
232 readerThread = 0;
233 int state = this.state;
234 if (state == ST_CLOSING)
235 tryFinishClose();
236 if (!completed && state >= ST_CLOSING)
237 throw new SocketException("Socket closed");
238 }
239 }
240
241 /**
242 * Attempts to read bytes from the socket into the given byte array.
243 */
244 private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
245 throws IOException
246 {
247 ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
248 assert dst.position() == 0;
249 try {
250 int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
251 if (n > 0) {
252 dst.get(b, off, n);
275 n = tryRead(fd, b, off, len);
276 }
277 return n;
278 }
279
280 /**
281 * Reads bytes from the socket into the given byte array.
282 * @return the number of bytes read or -1 at EOF
283 * @throws SocketException if the socket is closed or a socket I/O error occurs
284 * @throws SocketTimeoutException if the read timeout elapses
285 */
286 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
287 int n = 0;
288 SocketException ex = null;
289 FileDescriptor fd = beginRead();
290 try {
291 if (connectionReset)
292 throw new SocketException("Connection reset");
293 if (isInputClosed)
294 return -1;
295 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
296 if (remainingNanos > 0) {
297 // read with timeout
298 n = timedRead(fd, b, off, len, remainingNanos);
299 } else {
300 // read, no timeout
301 n = tryRead(fd, b, off, len);
302 while (IOStatus.okayToRetry(n) && isOpen()) {
303 park(fd, Net.POLLIN);
304 n = tryRead(fd, b, off, len);
305 }
306 }
307 } catch (InterruptedIOException e) {
308 throw e;
309 } catch (ConnectionResetException e) {
310 connectionReset = true;
311 throw new SocketException("Connection reset");
312 } catch (IOException ioe) {
313 // translate to SocketException to maintain compatibility
314 ex = asSocketException(ioe);
353 return -1;
354 // read up to Streams.MAX_BUFFER_SIZE bytes
355 int size = Math.min(len, Streams.MAX_BUFFER_SIZE);
356 int n = implRead(b, off, size, remainingNanos);
357 if (n == -1)
358 readEOF = true;
359 return n;
360 } finally {
361 readLock.unlock();
362 }
363 }
364 }
365
366 /**
367 * Marks the beginning of a write operation that might block.
368 * @throws SocketException if the socket is closed or not connected
369 */
370 private FileDescriptor beginWrite() throws SocketException {
371 synchronized (stateLock) {
372 ensureOpenAndConnected();
373 writerThread = NativeThread.current();
374 return fd;
375 }
376 }
377
378 /**
379 * Marks the end of a write operation that may have blocked.
380 * @throws SocketException is the socket is closed
381 */
382 private void endWrite(boolean completed) throws SocketException {
383 synchronized (stateLock) {
384 writerThread = 0;
385 int state = this.state;
386 if (state == ST_CLOSING)
387 tryFinishClose();
388 if (!completed && state >= ST_CLOSING)
389 throw new SocketException("Socket closed");
390 }
391 }
392
393 /**
394 * Attempts to write a sequence of bytes to the socket from the given
395 * byte array.
396 */
397 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
398 throws IOException
399 {
400 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
401 assert src.position() == 0;
402 try {
403 src.put(b, off, len);
404 return nd.write(fd, ((DirectBuffer)src).address(), len);
405 } finally {
406 Util.offerFirstTemporaryDirectBuffer(src);
407 }
408 }
409
410 /**
411 * Writes a sequence of bytes to the socket from the given byte array.
412 * @return the number of bytes written
413 * @throws SocketException if the socket is closed or a socket I/O error occurs
414 */
415 private int implWrite(byte[] b, int off, int len) throws IOException {
416 int n = 0;
417 SocketException ex = null;
418 FileDescriptor fd = beginWrite();
419 try {
420 configureNonBlockingIfNeeded(fd, false);
421 n = tryWrite(fd, b, off, len);
422 while (IOStatus.okayToRetry(n) && isOpen()) {
423 park(fd, Net.POLLOUT);
424 n = tryWrite(fd, b, off, len);
425 }
426 } catch (InterruptedIOException e) {
427 throw e;
428 } catch (IOException ioe) {
429 // translate to SocketException to maintain compatibility
430 ex = asSocketException(ioe);
431 } finally {
432 endWrite(n > 0);
433 }
434 if (ex != null) {
435 throw ex;
436 }
437 return n;
438 }
439
494 {
495 synchronized (stateLock) {
496 int state = this.state;
497 if (state != ST_UNCONNECTED) {
498 if (state == ST_NEW)
499 throw new SocketException("Not created");
500 if (state == ST_CONNECTING)
501 throw new SocketException("Connection in progress");
502 if (state == ST_CONNECTED)
503 throw new SocketException("Already connected");
504 if (state >= ST_CLOSING)
505 throw new SocketException("Socket closed");
506 assert false;
507 }
508 this.state = ST_CONNECTING;
509
510 // save the remote address/port
511 this.address = address;
512 this.port = port;
513
514 readerThread = NativeThread.current();
515 return fd;
516 }
517 }
518
519 /**
520 * Marks the end of a connect operation that may have blocked.
521 * @throws SocketException is the socket is closed
522 */
523 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
524 synchronized (stateLock) {
525 readerThread = 0;
526 int state = this.state;
527 if (state == ST_CLOSING)
528 tryFinishClose();
529 if (completed && state == ST_CONNECTING) {
530 this.state = ST_CONNECTED;
531 localport = Net.localAddress(fd).getPort();
532 } else if (!completed && state >= ST_CLOSING) {
533 throw new SocketException("Socket closed");
534 }
535 }
536 }
537
538 /**
539 * Waits for a connection attempt to finish with a timeout
540 * @throws SocketTimeoutException if the connect timeout elapses
541 */
542 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
543 long startNanos = System.nanoTime();
544 boolean polled = Net.pollConnectNow(fd);
545 while (!polled && isOpen()) {
649
650 @Override
651 protected void listen(int backlog) throws IOException {
652 synchronized (stateLock) {
653 ensureOpen();
654 if (localport == 0)
655 throw new SocketException("Not bound");
656 Net.listen(fd, backlog < 1 ? 50 : backlog);
657 }
658 }
659
660 /**
661 * Marks the beginning of an accept operation that might block.
662 * @throws SocketException if the socket is closed
663 */
664 private FileDescriptor beginAccept() throws SocketException {
665 synchronized (stateLock) {
666 ensureOpen();
667 if (localport == 0)
668 throw new SocketException("Not bound");
669 readerThread = NativeThread.current();
670 return fd;
671 }
672 }
673
674 /**
675 * Marks the end of an accept operation that may have blocked.
676 * @throws SocketException is the socket is closed
677 */
678 private void endAccept(boolean completed) throws SocketException {
679 synchronized (stateLock) {
680 int state = this.state;
681 readerThread = 0;
682 if (state == ST_CLOSING)
683 tryFinishClose();
684 if (!completed && state >= ST_CLOSING)
685 throw new SocketException("Socket closed");
686 }
687 }
688
689 /**
690 * Accepts a new connection with a timeout.
691 * @throws SocketTimeoutException if the accept timeout elapses
692 */
693 private int timedAccept(FileDescriptor fd,
694 FileDescriptor newfd,
695 InetSocketAddress[] isaa,
696 long nanos)
697 throws IOException
698 {
699 long startNanos = System.nanoTime();
700 int n = Net.accept(fd, newfd, isaa);
701 while (n == IOStatus.UNAVAILABLE && isOpen()) {
827 };
828 }
829
830 @Override
831 protected int available() throws IOException {
832 synchronized (stateLock) {
833 ensureOpenAndConnected();
834 if (isInputClosed) {
835 return 0;
836 } else {
837 return Net.available(fd);
838 }
839 }
840 }
841
842 /**
843 * Closes the socket if there are no I/O operations in progress.
844 */
845 private boolean tryClose() throws IOException {
846 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
847 if (readerThread == 0 && writerThread == 0) {
848 try {
849 cleaner.clean();
850 } catch (UncheckedIOException ioe) {
851 throw ioe.getCause();
852 } finally {
853 state = ST_CLOSED;
854 }
855 return true;
856 } else {
857 return false;
858 }
859 }
860
861 /**
862 * Invokes tryClose to attempt to close the socket.
863 *
864 * This method is used for deferred closing by I/O operations.
865 */
866 private void tryFinishClose() {
867 try {
1126 if (!Net.isReusePortAvailable())
1127 throw new SocketException("SO_REUSEPORT not supported");
1128 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1129 default:
1130 throw new SocketException("Unknown option " + opt);
1131 }
1132 } catch (SocketException e) {
1133 throw e;
1134 } catch (IllegalArgumentException | IOException e) {
1135 throw asSocketException(e);
1136 }
1137 }
1138 }
1139
1140 @Override
1141 protected void shutdownInput() throws IOException {
1142 synchronized (stateLock) {
1143 ensureOpenAndConnected();
1144 if (!isInputClosed) {
1145 Net.shutdown(fd, Net.SHUT_RD);
1146 if (NativeThread.isVirtualThread(readerThread)) {
1147 Poller.stopPoll(fdVal(fd), Net.POLLIN);
1148 }
1149 isInputClosed = true;
1150 }
1151 }
1152 }
1153
1154 @Override
1155 protected void shutdownOutput() throws IOException {
1156 synchronized (stateLock) {
1157 ensureOpenAndConnected();
1158 if (!isOutputClosed) {
1159 Net.shutdown(fd, Net.SHUT_WR);
1160 if (NativeThread.isVirtualThread(writerThread)) {
1161 Poller.stopPoll(fdVal(fd), Net.POLLOUT);
1162 }
1163 isOutputClosed = true;
1164 }
1165 }
1166 }
1167
1168 @Override
1169 protected boolean supportsUrgentData() {
1170 return true;
1171 }
1172
1173 @Override
1174 protected void sendUrgentData(int data) throws IOException {
1175 writeLock.lock();
1176 try {
1177 int n = 0;
1178 FileDescriptor fd = beginWrite();
1179 try {
1180 configureNonBlockingIfNeeded(fd, false);
1181 do {
|
86
87 // Lock held when writing
88 private final ReentrantLock writeLock = new ReentrantLock();
89
90 // The stateLock for read/changing state
91 private final Object stateLock = new Object();
92 private static final int ST_NEW = 0;
93 private static final int ST_UNCONNECTED = 1;
94 private static final int ST_CONNECTING = 2;
95 private static final int ST_CONNECTED = 3;
96 private static final int ST_CLOSING = 4;
97 private static final int ST_CLOSED = 5;
98 private volatile int state; // need stateLock to change
99
100 private Cleanable cleaner;
101
102 // set to true when the socket is in non-blocking mode
103 private volatile boolean nonBlocking;
104
105 // used by connect/read/write/accept, protected by stateLock
106 private Thread readerThread;
107 private Thread writerThread;
108
109 // used when SO_REUSEADDR is emulated, protected by stateLock
110 private boolean isReuseAddress;
111
112 // read or accept timeout in millis
113 private volatile int timeout;
114
115 // flags to indicate if the connection is shutdown for input and output
116 private volatile boolean isInputClosed;
117 private volatile boolean isOutputClosed;
118
119 // used by read to emulate legacy behavior, protected by readLock
120 private boolean readEOF;
121 private boolean connectionReset;
122
123 /**
124 * Creates an instance of this SocketImpl.
125 * @param server true if this is a SocketImpl for a ServerSocket
126 */
127 public NioSocketImpl(boolean server) {
201 * @throws IOException if there is an I/O error changing the blocking mode
202 */
203 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
204 throws IOException
205 {
206 if (!nonBlocking
207 && (timed || Thread.currentThread().isVirtual())) {
208 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
209 IOUtil.configureBlocking(fd, false);
210 nonBlocking = true;
211 }
212 }
213
214 /**
215 * Marks the beginning of a read operation that might block.
216 * @throws SocketException if the socket is closed or not connected
217 */
218 private FileDescriptor beginRead() throws SocketException {
219 synchronized (stateLock) {
220 ensureOpenAndConnected();
221 readerThread = NativeThread.threadToSignal();
222 return fd;
223 }
224 }
225
226 /**
227 * Marks the end of a read operation that may have blocked.
228 * @throws SocketException is the socket is closed
229 */
230 private void endRead(boolean completed) throws SocketException {
231 synchronized (stateLock) {
232 readerThread = null;
233 int state = this.state;
234 if (state == ST_CLOSING)
235 tryFinishClose();
236 if (!completed && state >= ST_CLOSING)
237 throw new SocketException("Socket closed");
238 }
239 }
240
241 /**
242 * Attempts to read bytes from the socket into the given byte array.
243 */
244 private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
245 throws IOException
246 {
247 ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
248 assert dst.position() == 0;
249 try {
250 int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
251 if (n > 0) {
252 dst.get(b, off, n);
275 n = tryRead(fd, b, off, len);
276 }
277 return n;
278 }
279
280 /**
281 * Reads bytes from the socket into the given byte array.
282 * @return the number of bytes read or -1 at EOF
283 * @throws SocketException if the socket is closed or a socket I/O error occurs
284 * @throws SocketTimeoutException if the read timeout elapses
285 */
286 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
287 int n = 0;
288 SocketException ex = null;
289 FileDescriptor fd = beginRead();
290 try {
291 if (connectionReset)
292 throw new SocketException("Connection reset");
293 if (isInputClosed)
294 return -1;
295
296 // experimental
297 if (Poller.supportReadOps() && Thread.currentThread().isVirtual()) {
298 n = Poller.read(fdVal(fd), b, off, len, remainingNanos, this::isOpen);
299 if (n != IOStatus.UNAVAILABLE) return n;
300 }
301
302 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
303 if (remainingNanos > 0) {
304 // read with timeout
305 n = timedRead(fd, b, off, len, remainingNanos);
306 } else {
307 // read, no timeout
308 n = tryRead(fd, b, off, len);
309 while (IOStatus.okayToRetry(n) && isOpen()) {
310 park(fd, Net.POLLIN);
311 n = tryRead(fd, b, off, len);
312 }
313 }
314 } catch (InterruptedIOException e) {
315 throw e;
316 } catch (ConnectionResetException e) {
317 connectionReset = true;
318 throw new SocketException("Connection reset");
319 } catch (IOException ioe) {
320 // translate to SocketException to maintain compatibility
321 ex = asSocketException(ioe);
360 return -1;
361 // read up to Streams.MAX_BUFFER_SIZE bytes
362 int size = Math.min(len, Streams.MAX_BUFFER_SIZE);
363 int n = implRead(b, off, size, remainingNanos);
364 if (n == -1)
365 readEOF = true;
366 return n;
367 } finally {
368 readLock.unlock();
369 }
370 }
371 }
372
373 /**
374 * Marks the beginning of a write operation that might block.
375 * @throws SocketException if the socket is closed or not connected
376 */
377 private FileDescriptor beginWrite() throws SocketException {
378 synchronized (stateLock) {
379 ensureOpenAndConnected();
380 writerThread = NativeThread.threadToSignal();
381 return fd;
382 }
383 }
384
385 /**
386 * Marks the end of a write operation that may have blocked.
387 * @throws SocketException is the socket is closed
388 */
389 private void endWrite(boolean completed) throws SocketException {
390 synchronized (stateLock) {
391 writerThread = null;
392 int state = this.state;
393 if (state == ST_CLOSING)
394 tryFinishClose();
395 if (!completed && state >= ST_CLOSING)
396 throw new SocketException("Socket closed");
397 }
398 }
399
400 /**
401 * Attempts to write a sequence of bytes to the socket from the given
402 * byte array.
403 */
404 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
405 throws IOException
406 {
407 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
408 assert src.position() == 0;
409 try {
410 src.put(b, off, len);
411 return nd.write(fd, ((DirectBuffer)src).address(), len);
412 } finally {
413 Util.offerFirstTemporaryDirectBuffer(src);
414 }
415 }
416
417 /**
418 * Writes a sequence of bytes to the socket from the given byte array.
419 * @return the number of bytes written
420 * @throws SocketException if the socket is closed or a socket I/O error occurs
421 */
422 private int implWrite(byte[] b, int off, int len) throws IOException {
423 int n = 0;
424 SocketException ex = null;
425 FileDescriptor fd = beginWrite();
426 try {
427
428 // experimental
429 if (Poller.supportWriteOps() && Thread.currentThread().isVirtual()) {
430 n = Poller.write(fdVal(fd), b, off, len, this::isOpen);
431 if (n != IOStatus.UNAVAILABLE) return n;
432 }
433
434 configureNonBlockingIfNeeded(fd, false);
435 n = tryWrite(fd, b, off, len);
436 while (IOStatus.okayToRetry(n) && isOpen()) {
437 park(fd, Net.POLLOUT);
438 n = tryWrite(fd, b, off, len);
439 }
440 } catch (InterruptedIOException e) {
441 throw e;
442 } catch (IOException ioe) {
443 // translate to SocketException to maintain compatibility
444 ex = asSocketException(ioe);
445 } finally {
446 endWrite(n > 0);
447 }
448 if (ex != null) {
449 throw ex;
450 }
451 return n;
452 }
453
508 {
509 synchronized (stateLock) {
510 int state = this.state;
511 if (state != ST_UNCONNECTED) {
512 if (state == ST_NEW)
513 throw new SocketException("Not created");
514 if (state == ST_CONNECTING)
515 throw new SocketException("Connection in progress");
516 if (state == ST_CONNECTED)
517 throw new SocketException("Already connected");
518 if (state >= ST_CLOSING)
519 throw new SocketException("Socket closed");
520 assert false;
521 }
522 this.state = ST_CONNECTING;
523
524 // save the remote address/port
525 this.address = address;
526 this.port = port;
527
528 readerThread = NativeThread.threadToSignal();
529 return fd;
530 }
531 }
532
533 /**
534 * Marks the end of a connect operation that may have blocked.
535 * @throws SocketException is the socket is closed
536 */
537 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
538 synchronized (stateLock) {
539 readerThread = null;
540 int state = this.state;
541 if (state == ST_CLOSING)
542 tryFinishClose();
543 if (completed && state == ST_CONNECTING) {
544 this.state = ST_CONNECTED;
545 localport = Net.localAddress(fd).getPort();
546 } else if (!completed && state >= ST_CLOSING) {
547 throw new SocketException("Socket closed");
548 }
549 }
550 }
551
552 /**
553 * Waits for a connection attempt to finish with a timeout
554 * @throws SocketTimeoutException if the connect timeout elapses
555 */
556 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
557 long startNanos = System.nanoTime();
558 boolean polled = Net.pollConnectNow(fd);
559 while (!polled && isOpen()) {
663
664 @Override
665 protected void listen(int backlog) throws IOException {
666 synchronized (stateLock) {
667 ensureOpen();
668 if (localport == 0)
669 throw new SocketException("Not bound");
670 Net.listen(fd, backlog < 1 ? 50 : backlog);
671 }
672 }
673
674 /**
675 * Marks the beginning of an accept operation that might block.
676 * @throws SocketException if the socket is closed
677 */
678 private FileDescriptor beginAccept() throws SocketException {
679 synchronized (stateLock) {
680 ensureOpen();
681 if (localport == 0)
682 throw new SocketException("Not bound");
683 readerThread = NativeThread.threadToSignal();
684 return fd;
685 }
686 }
687
688 /**
689 * Marks the end of an accept operation that may have blocked.
690 * @throws SocketException is the socket is closed
691 */
692 private void endAccept(boolean completed) throws SocketException {
693 synchronized (stateLock) {
694 int state = this.state;
695 readerThread = null;
696 if (state == ST_CLOSING)
697 tryFinishClose();
698 if (!completed && state >= ST_CLOSING)
699 throw new SocketException("Socket closed");
700 }
701 }
702
703 /**
704 * Accepts a new connection with a timeout.
705 * @throws SocketTimeoutException if the accept timeout elapses
706 */
707 private int timedAccept(FileDescriptor fd,
708 FileDescriptor newfd,
709 InetSocketAddress[] isaa,
710 long nanos)
711 throws IOException
712 {
713 long startNanos = System.nanoTime();
714 int n = Net.accept(fd, newfd, isaa);
715 while (n == IOStatus.UNAVAILABLE && isOpen()) {
841 };
842 }
843
844 @Override
845 protected int available() throws IOException {
846 synchronized (stateLock) {
847 ensureOpenAndConnected();
848 if (isInputClosed) {
849 return 0;
850 } else {
851 return Net.available(fd);
852 }
853 }
854 }
855
856 /**
857 * Closes the socket if there are no I/O operations in progress.
858 */
859 private boolean tryClose() throws IOException {
860 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
861 if (readerThread == null && writerThread == null) {
862 try {
863 cleaner.clean();
864 } catch (UncheckedIOException ioe) {
865 throw ioe.getCause();
866 } finally {
867 state = ST_CLOSED;
868 }
869 return true;
870 } else {
871 return false;
872 }
873 }
874
875 /**
876 * Invokes tryClose to attempt to close the socket.
877 *
878 * This method is used for deferred closing by I/O operations.
879 */
880 private void tryFinishClose() {
881 try {
1140 if (!Net.isReusePortAvailable())
1141 throw new SocketException("SO_REUSEPORT not supported");
1142 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1143 default:
1144 throw new SocketException("Unknown option " + opt);
1145 }
1146 } catch (SocketException e) {
1147 throw e;
1148 } catch (IllegalArgumentException | IOException e) {
1149 throw asSocketException(e);
1150 }
1151 }
1152 }
1153
1154 @Override
1155 protected void shutdownInput() throws IOException {
1156 synchronized (stateLock) {
1157 ensureOpenAndConnected();
1158 if (!isInputClosed) {
1159 Net.shutdown(fd, Net.SHUT_RD);
1160 if (readerThread != null && readerThread.isVirtual()) {
1161 Poller.stopPoll(readerThread);
1162 }
1163 isInputClosed = true;
1164 }
1165 }
1166 }
1167
1168 @Override
1169 protected void shutdownOutput() throws IOException {
1170 synchronized (stateLock) {
1171 ensureOpenAndConnected();
1172 if (!isOutputClosed) {
1173 Net.shutdown(fd, Net.SHUT_WR);
1174 if (writerThread != null && writerThread.isVirtual()) {
1175 Poller.stopPoll(writerThread);
1176 }
1177 isOutputClosed = true;
1178 }
1179 }
1180 }
1181
1182 @Override
1183 protected boolean supportsUrgentData() {
1184 return true;
1185 }
1186
1187 @Override
1188 protected void sendUrgentData(int data) throws IOException {
1189 writeLock.lock();
1190 try {
1191 int n = 0;
1192 FileDescriptor fd = beginWrite();
1193 try {
1194 configureNonBlockingIfNeeded(fd, false);
1195 do {
|