private void callAfterAdd(ChannelHandlerContext ctx) {
    try {
      ctx.handler().afterAdd(ctx);
    } catch (Throwable t) {
      boolean removed = false;
      try {
        remove((DefaultChannelHandlerContext) ctx, false);
        removed = true;
      } catch (Throwable t2) {
        if (logger.isWarnEnabled()) {
          logger.warn("Failed to remove a handler: " + ctx.name(), t2);
        }
      }

      if (removed) {
        throw new ChannelPipelineException(
            ctx.handler().getClass().getName() + ".afterAdd() has thrown an exception; removed.",
            t);
      } else {
        throw new ChannelPipelineException(
            ctx.handler().getClass().getName()
                + ".afterAdd() has thrown an exception; also failed to remove.",
            t);
      }
    }
  }
 @Override
 protected void messageReceived(ChannelHandlerContext ctx, Freeable msg) throws Exception {
   if (logger.isWarnEnabled()) {
     logger.warn(
         "Freeable reached end-of-pipeline, call "
             + msg
             + ".free() to"
             + " guard against resource leakage!");
   }
   msg.free();
 }
示例#3
0
  void register(SctpChannelImpl channel, ChannelFuture future) {

    boolean server = !(channel instanceof SctpClientChannel);
    Runnable registerTask = new RegisterTask(channel, future, server);
    notificationHandler = new SctpNotificationHandler(channel);
    Selector selector;

    synchronized (startStopLock) {
      if (!started) {
        // Open a selector if this worker didn't start yet.
        try {
          this.selector = selector = Selector.open();
        } catch (Throwable t) {
          throw new ChannelException("Failed to create a selector.", t);
        }

        // Start the worker thread with the new Selector.
        boolean success = false;
        try {
          DeadLockProofWorker.start(executor, this);
          success = true;
        } finally {
          if (!success) {
            // Release the Selector if the execution fails.
            try {
              selector.close();
            } catch (Throwable t) {
              if (logger.isWarnEnabled()) {
                logger.warn("Failed to close a selector.", t);
              }
            }
            this.selector = selector = null;
            // The method will return to the caller at this point.
          }
        }
      } else {
        // Use the existing selector if this worker has been started.
        selector = this.selector;
      }

      assert selector != null && selector.isOpen();

      started = true;
      boolean offered = registerTaskQueue.offer(registerTask);
      assert offered;
    }

    if (wakenUp.compareAndSet(false, true)) {
      selector.wakeup();
    }
  }
  void notifyHandlerException(Throwable cause) {
    if (!(cause instanceof ChannelPipelineException)) {
      cause = new ChannelPipelineException(cause);
    }

    if (inExceptionCaught(cause)) {
      if (logger.isWarnEnabled()) {
        logger.warn(
            "An exception was thrown by a user handler "
                + "while handling an exceptionCaught event",
            cause);
      }
      return;
    }

    fireExceptionCaught(cause);
  }
  public NioSocketChannel(Channel parent, Integer id, SocketChannel socket) {
    // socket就是ch
    super(parent, id, socket);
    try {
      // 设置socketchannel非阻塞
      socket.configureBlocking(false);
    } catch (IOException e) {
      try {
        socket.close();
      } catch (IOException e2) {
        if (logger.isWarnEnabled()) {
          logger.warn("Failed to close a partially initialized socket.", e2);
        }
      }

      throw new ChannelException("Failed to enter non-blocking mode.", e);
    }

    config = new DefaultSocketChannelConfig(socket.socket());
  }
示例#6
0
  @Override
  public void run() {
    thread = Thread.currentThread();

    boolean shutdown = false;
    Selector selector = this.selector;
    for (; ; ) {
      wakenUp.set(false);

      if (CONSTRAINT_LEVEL != 0) {
        selectorGuard.writeLock().lock();
        // This empty synchronization block prevents the selector
        // from acquiring its lock.
        selectorGuard.writeLock().unlock();
      }

      try {
        SelectorUtil.select(selector);

        // 'wakenUp.compareAndSet(false, true)' is always evaluated
        // before calling 'selector.wakeup()' to reduce the wake-up
        // overhead. (Selector.wakeup() is an expensive operation.)
        //
        // However, there is a race condition in this approach.
        // The race condition is triggered when 'wakenUp' is set to
        // true too early.
        //
        // 'wakenUp' is set to true too early if:
        // 1) Selector is waken up between 'wakenUp.set(false)' and
        //    'selector.select(...)'. (BAD)
        // 2) Selector is waken up between 'selector.select(...)' and
        //    'if (wakenUp.get()) { ... }'. (OK)
        //
        // In the first case, 'wakenUp' is set to true and the
        // following 'selector.select(...)' will wake up immediately.
        // Until 'wakenUp' is set to false again in the next round,
        // 'wakenUp.compareAndSet(false, true)' will fail, and therefore
        // any attempt to wake up the Selector will fail, too, causing
        // the following 'selector.select(...)' call to block
        // unnecessarily.
        //
        // To fix this problem, we wake up the selector again if wakenUp
        // is true immediately after selector.select(...).
        // It is inefficient in that it wakes up the selector for both
        // the first case (BAD - wake-up required) and the second case
        // (OK - no wake-up required).

        if (wakenUp.get()) {
          selector.wakeup();
        }

        cancelledKeys = 0;
        processRegisterTaskQueue();
        processEventQueue();
        processWriteTaskQueue();
        processSelectedKeys(selector.selectedKeys());

        // Exit the loop when there's nothing to handle.
        // The shutdown flag is used to delay the shutdown of this
        // loop to avoid excessive Selector creation when
        // connections are registered in a one-by-one manner instead of
        // concurrent manner.
        if (selector.keys().isEmpty()) {
          if (shutdown
              || executor instanceof ExecutorService && ((ExecutorService) executor).isShutdown()) {

            synchronized (startStopLock) {
              if (registerTaskQueue.isEmpty() && selector.keys().isEmpty()) {
                started = false;
                try {
                  selector.close();
                } catch (IOException e) {
                  if (logger.isWarnEnabled()) {
                    logger.warn("Failed to close a selector.", e);
                  }
                } finally {
                  this.selector = null;
                }
                break;
              } else {
                shutdown = false;
              }
            }
          } else {
            // Give one more second.
            shutdown = true;
          }
        } else {
          shutdown = false;
        }
      } catch (Throwable t) {
        if (logger.isWarnEnabled()) {
          logger.warn("Unexpected exception in the selector loop.", t);
        }
        // Prevent possible consecutive immediate failures that lead to
        // excessive CPU consumption.
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          // Ignore.
        }
      }
    }
  }