@Override
        public void run() {
          int numElements = new Exception().getStackTrace().length;
          int depth = executed.getAndIncrement();
          if (depth <= IPCUtil.MAX_DEPTH) {
            if (numElements <= numStackTraceElements.intValue()) {
              future.completeExceptionally(
                new AssertionError("should call run directly but stack trace decreased from "
                  + numStackTraceElements.intValue() + " to " + numElements));
              return;
            }
            numStackTraceElements.setValue(numElements);
            IPCUtil.execute(eventLoop, this);
          } else {
            if (numElements >= numStackTraceElements.intValue()) {
              future.completeExceptionally(
                new AssertionError("should call eventLoop.execute to prevent stack overflow but"
                  + " stack trace increased from " + numStackTraceElements.intValue() + " to "
                  + numElements));
            } else {
              future.complete(null);
            }
          }
        }
See HBASE-21862, it is important to keep original exception type for connection exceptions.
hbase-client/src/test/java/org/apache/hadoop/hbase/ipc/TestIPCUtil.java