(@Nullable Throwable ex, boolean gracefully)
| 714 | } |
| 715 | |
| 716 | @Override |
| 717 | public boolean close(@Nullable Throwable ex, boolean gracefully) { |
| 718 | if (!closedHandle.compareAndSet(this, (byte)0, (byte)1)) // 阻止递归关闭 |
| 719 | return false; |
| 720 | |
| 721 | if (ex != null) { |
| 722 | if (ex instanceof IOException) |
| 723 | logger.info("close: {} {}", this, ex); |
| 724 | else |
| 725 | logger.warn("close: {} exception:", this, ex); |
| 726 | } else |
| 727 | logger.info("close: {}{}", this, gracefully ? " gracefully" : ""); |
| 728 | |
| 729 | if (acceptorOrConnector instanceof Connector) { |
| 730 | try { |
| 731 | ((Connector)acceptorOrConnector).OnSocketClose(this, ex); |
| 732 | } catch (Exception e) { |
| 733 | logger.error("Connector.OnSocketClose exception:", e); |
| 734 | } |
| 735 | } |
| 736 | try { |
| 737 | getService().OnSocketClose(this, ex); |
| 738 | } catch (Exception e) { |
| 739 | logger.error("Service.OnSocketClose exception:", e); |
| 740 | } |
| 741 | |
| 742 | if (gracefully) { |
| 743 | closePending = true; |
| 744 | if (addInterestOps(SelectionKey.OP_WRITE)) |
| 745 | selector.wakeup(); |
| 746 | Task.schedule(120 * 1000, this::realClose); // 最多给2分钟清空输出队列。 |
| 747 | } else |
| 748 | realClose(); |
| 749 | return true; |
| 750 | } |
| 751 | |
| 752 | @Override |
| 753 | public @NotNull String toString() { |
no test coverage detected