Fix IllegalReferenceCountException caused by HttpClientCodec.upgradeFrom()

Motivation:

On a successful protocol upgrade in HTTP, HttpClientUpgradeHandler calls
HttpClientCodec.upgradeFrom(), which removed both the HTTP encoder and
decoder from the pipeline immediately.

However, because the decoder is in the middle of the decode loop,
removing it from the pipeline immediately will cause the cumulation
buffer to be released prematurely.

This often leads to an IllegalReferenceCountException or missing first
response after the upgrade response.

Modifications:

- Remove the decoder *after* the decode loop is done

Result:

Fixes #4504
This commit is contained in:
Trustin Lee 2015-11-29 13:36:32 +09:00 committed by Norman Maurer
parent 6d48a6ebd8
commit 0d7caac883

View File

@ -19,7 +19,9 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerAppender;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.PrematureChannelClosureException;
import io.netty.util.internal.OneTimeTask;
import java.util.ArrayDeque;
import java.util.List;
@ -93,8 +95,15 @@ public final class HttpClientCodec extends ChannelHandlerAppender implements
*/
@Override
public void upgradeFrom(ChannelHandlerContext ctx) {
ctx.pipeline().remove(Decoder.class);
ctx.pipeline().remove(Encoder.class);
final ChannelPipeline p = ctx.pipeline();
// Remove the decoder later so that the decoder can enter the 'UPGRADED' state and forward the remaining data.
ctx.executor().execute(new OneTimeTask() {
@Override
public void run() {
p.remove(decoder());
}
});
p.remove(encoder());
}
/**