[#1442] Make sure closing the channel will not cause an UnsupportedOperationException
This commit is contained in:
parent
e5ca6518ba
commit
a1a86b9de4
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
if (!tearDown) {
|
||||
ctx.setRemoved();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
fireExceptionCaught(new ChannelPipelineException(
|
||||
ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t));
|
||||
|
Loading…
Reference in New Issue
Block a user