Revert "[#1442] Make sure closing the channel will not cause an UnsupportedOperationException"

This reverts commit a1a86b9de4 because the
semantic of ctx.isRemoved() is confusing to a user - why is
ctx.isRemoved() false when handlerRemoved() is invoked? A better
solution would be check if the connection is inactive and mark the
promise as failure before attempting to write anything.
This commit is contained in:
Trustin Lee 2013-06-14 10:47:31 +09:00
parent 30bfb989c1
commit 25c51279cf
2 changed files with 11 additions and 13 deletions

View File

@ -125,7 +125,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
DefaultChannelHandlerContext prev = this.prev; DefaultChannelHandlerContext prev = this.prev;
if (prev != null) { if (prev != null) {
synchronized (pipeline) { synchronized (pipeline) {
pipeline.remove0(this, true); pipeline.remove0(this);
} }
prev.teardown(); prev.teardown();
} }

View File

@ -316,14 +316,14 @@ final class DefaultChannelPipeline implements ChannelPipeline {
synchronized (this) { synchronized (this) {
if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) {
remove0(ctx, false); remove0(ctx);
return ctx; return ctx;
} else { } else {
future = ctx.executor().submit(new Runnable() { future = ctx.executor().submit(new Runnable() {
@Override @Override
public void run() { public void run() {
synchronized (DefaultChannelPipeline.this) { synchronized (DefaultChannelPipeline.this) {
remove0(ctx, false); remove0(ctx);
} }
} }
}); });
@ -339,13 +339,13 @@ final class DefaultChannelPipeline implements ChannelPipeline {
return context; return context;
} }
void remove0(DefaultChannelHandlerContext ctx, boolean tearDown) { void remove0(DefaultChannelHandlerContext ctx) {
DefaultChannelHandlerContext prev = ctx.prev; DefaultChannelHandlerContext prev = ctx.prev;
DefaultChannelHandlerContext next = ctx.next; DefaultChannelHandlerContext next = ctx.next;
prev.next = next; prev.next = next;
next.prev = prev; next.prev = prev;
name2ctx.remove(ctx.name()); name2ctx.remove(ctx.name());
callHandlerRemoved(ctx, tearDown); callHandlerRemoved(ctx);
} }
@Override @Override
@ -450,7 +450,7 @@ final class DefaultChannelPipeline implements ChannelPipeline {
// because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those // because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those
// event handlers must be called after handlerAdded(). // event handlers must be called after handlerAdded().
callHandlerAdded(newCtx); callHandlerAdded(newCtx);
callHandlerRemoved(oldCtx, false); callHandlerRemoved(oldCtx);
} }
private static void checkMultiplicity(ChannelHandlerContext ctx) { private static void checkMultiplicity(ChannelHandlerContext ctx) {
@ -505,26 +505,24 @@ final class DefaultChannelPipeline implements ChannelPipeline {
} }
} }
private void callHandlerRemoved(final DefaultChannelHandlerContext ctx, final boolean tearDown) { private void callHandlerRemoved(final DefaultChannelHandlerContext ctx) {
if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) {
ctx.executor().execute(new Runnable() { ctx.executor().execute(new Runnable() {
@Override @Override
public void run() { public void run() {
callHandlerRemoved0(ctx, tearDown); callHandlerRemoved0(ctx);
} }
}); });
return; return;
} }
callHandlerRemoved0(ctx, tearDown); callHandlerRemoved0(ctx);
} }
private void callHandlerRemoved0(final DefaultChannelHandlerContext ctx, boolean tearDown) { private void callHandlerRemoved0(final DefaultChannelHandlerContext ctx) {
// Notify the complete removal. // Notify the complete removal.
try { try {
ctx.handler().handlerRemoved(ctx); ctx.handler().handlerRemoved(ctx);
if (!tearDown) { ctx.setRemoved();
ctx.setRemoved();
}
} catch (Throwable t) { } catch (Throwable t) {
fireExceptionCaught(new ChannelPipelineException( fireExceptionCaught(new ChannelPipelineException(
ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t)); ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t));