From a1a86b9de48e4696e3496904dd972336f57b4a0b Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 13 Jun 2013 18:10:56 +0200 Subject: [PATCH] [#1442] Make sure closing the channel will not cause an UnsupportedOperationException --- .../channel/DefaultChannelHandlerContext.java | 2 +- .../netty/channel/DefaultChannelPipeline.java | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java index b16b5bdcc8..59d17555e9 100755 --- a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java @@ -125,7 +125,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements DefaultChannelHandlerContext prev = this.prev; if (prev != null) { synchronized (pipeline) { - pipeline.remove0(this); + pipeline.remove0(this, true); } prev.teardown(); } diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java index 4a099291a4..2388cecab6 100755 --- a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java @@ -316,14 +316,14 @@ final class DefaultChannelPipeline implements ChannelPipeline { synchronized (this) { if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { - remove0(ctx); + remove0(ctx, false); return ctx; } else { future = ctx.executor().submit(new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { - remove0(ctx); + remove0(ctx, false); } } }); @@ -339,13 +339,13 @@ final class DefaultChannelPipeline implements ChannelPipeline { return context; } - void remove0(DefaultChannelHandlerContext ctx) { + void remove0(DefaultChannelHandlerContext ctx, boolean tearDown) { DefaultChannelHandlerContext prev = ctx.prev; DefaultChannelHandlerContext next = ctx.next; prev.next = next; next.prev = prev; name2ctx.remove(ctx.name()); - callHandlerRemoved(ctx); + callHandlerRemoved(ctx, tearDown); } @Override @@ -450,7 +450,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { // because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those // event handlers must be called after handlerAdded(). callHandlerAdded(newCtx); - callHandlerRemoved(oldCtx); + callHandlerRemoved(oldCtx, false); } private static void checkMultiplicity(ChannelHandlerContext ctx) { @@ -505,24 +505,26 @@ final class DefaultChannelPipeline implements ChannelPipeline { } } - private void callHandlerRemoved(final DefaultChannelHandlerContext ctx) { + private void callHandlerRemoved(final DefaultChannelHandlerContext ctx, final boolean tearDown) { if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { ctx.executor().execute(new Runnable() { @Override public void run() { - callHandlerRemoved0(ctx); + callHandlerRemoved0(ctx, tearDown); } }); return; } - callHandlerRemoved0(ctx); + callHandlerRemoved0(ctx, tearDown); } - private void callHandlerRemoved0(final DefaultChannelHandlerContext ctx) { + private void callHandlerRemoved0(final DefaultChannelHandlerContext ctx, boolean tearDown) { // Notify the complete removal. try { ctx.handler().handlerRemoved(ctx); - ctx.setRemoved(); + if (!tearDown) { + ctx.setRemoved(); + } } catch (Throwable t) { fireExceptionCaught(new ChannelPipelineException( ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t));