void removeEndpoint(DistributedMember memberID, String reason, boolean notifyDisconnect) {
    if (closed) {
      return;
    }
    boolean needsRemoval = false;
    synchronized (orderedConnectionMap) {
      if (orderedConnectionMap.get(memberID) != null) {
        needsRemoval = true;
      }
    }
    if (!needsRemoval) {
      synchronized (unorderedConnectionMap) {
        if (unorderedConnectionMap.get(memberID) != null) {
          needsRemoval = true;
        }
      }
    }
    if (!needsRemoval) {
      final ConcurrentMap<DistributedMember, List<Connection>> cm = threadConnectionMap;
      if (cm != null) {
        final List<Connection> al = cm.get(memberID);
        needsRemoval = al != null && !al.isEmpty();
      }
    }

    if (needsRemoval) {
      InternalDistributedMember remoteAddress = null;
      synchronized (orderedConnectionMap) {
        Object c = orderedConnectionMap.remove(memberID);
        if (c instanceof Connection) {
          remoteAddress = ((Connection) c).getRemoteAddress();
        }
        closeCon(reason, c);
      }
      synchronized (unorderedConnectionMap) {
        Object c = unorderedConnectionMap.remove(memberID);
        if (remoteAddress == null && c instanceof Connection) {
          remoteAddress = ((Connection) c).getRemoteAddress();
        }
        closeCon(reason, c);
      }

      final ConcurrentMap<DistributedMember, List<Connection>> cm = threadConnectionMap;
      if (cm != null) {
        final List<Connection> al = cm.remove(memberID);
        if (al != null) {
          synchronized (al) {
            for (Connection c : al) {
              if (remoteAddress == null && c != null) {
                remoteAddress = c.getRemoteAddress();
              }
              closeCon(reason, c);
            }
            al.clear();
          }
        }
      }

      // close any sockets that are in the process of being connected
      final Set<Socket> toRemove = new HashSet<>();
      synchronized (connectingSockets) {
        for (final Iterator<Map.Entry<Socket, ConnectingSocketInfo>> it =
            connectingSockets.entrySet().iterator(); it.hasNext();) {
          final Map.Entry<Socket, ConnectingSocketInfo> entry = it.next();
          final ConnectingSocketInfo info = entry.getValue();
          if (info.peerAddress.equals(((MemberIdentifier) memberID).getInetAddress())) {
            toRemove.add(entry.getKey());
            it.remove();
          }
        }
      }

      for (final Socket sock : toRemove) {
        try {
          sock.close();
        } catch (IOException e) {
          if (logger.isDebugEnabled()) {
            logger.debug("caught exception while trying to close connecting socket for {}",
                memberID, e);
          }
        }
      }

      // close any receivers
      // avoid deadlock when a NIC has failed by closing connections outside of the receivers sync
      final Set<Connection> connectionsToClose = new HashSet<>();
      synchronized (receivers) {
        for (final Iterator<Connection> it = receivers.iterator(); it.hasNext();) {
          final Connection con = it.next();
          if (memberID.equals(con.getRemoteAddress())) {
            it.remove();
            connectionsToClose.add(con);
          }
        }
      }
      for (final Connection con : connectionsToClose) {
        closeCon(reason, con);
      }
      if (notifyDisconnect) {
        if (owner.getDM().shutdownInProgress()) {
          throw new DistributedSystemDisconnectedException("Shutdown in progress",
              owner.getDM().getDistribution().getShutdownCause());
        }
      }

      if (remoteAddress != null) {
        socketCloser.releaseResourcesForAddress(remoteAddress.toString());
      }
    }
  }
remove an endpoint and notify the membership manager of the departure
geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java