From f00160bca36d9f795f015b78349f2be800674be0 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 7 May 2020 08:11:33 +0200 Subject: [PATCH] Don't reuse ChannelPromise in WebSocketProtocolHandler (#10248) Motivation: We cant reuse the ChannelPromise as it will cause an error when trying to ful-fill it multiple times. Modifications: - Use a new promise and chain it with the old one - Add unit test Result: Fixes https://github.com/netty/netty/issues/10240 --- .../websocketx/WebSocketProtocolHandler.java | 12 +++---- .../WebSocketProtocolHandlerTest.java | 35 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java index ccbccac0d0..547fc358a8 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java @@ -21,6 +21,7 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.ChannelPromiseNotifier; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.ScheduledFuture; @@ -110,13 +111,12 @@ abstract class WebSocketProtocolHandler extends MessageToMessageDecoder ref = new AtomicReference(); + WebSocketProtocolHandler handler = new WebSocketProtocolHandler( + false, WebSocketCloseStatus.NORMAL_CLOSURE, 1) { }; + EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter() { + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { + ref.set(promise); + ReferenceCountUtil.release(msg); + } + }, handler); + + ChannelFuture future = channel.writeAndFlush(new CloseWebSocketFrame()); + ChannelHandlerContext ctx = channel.pipeline().context(WebSocketProtocolHandler.class); + handler.close(ctx, ctx.newPromise()); + + do { + Thread.sleep(10); + channel.runPendingTasks(); + } while (!future.isDone()); + + assertThat(future.cause(), Matchers.instanceOf(WebSocketHandshakeException.class)); + assertFalse(ref.get().isDone()); + assertFalse(channel.finish()); + } + /** * Asserts that a message was propagated inbound through the channel. */