@@ -165,10 +165,15 @@ private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
165165
166166 private void handleWebSocketFrame (ChannelHandlerContext ctx , WebSocketFrame frame ) {
167167 if (frame instanceof CloseWebSocketFrame ) {
168- CloseWebSocketFrame close = (CloseWebSocketFrame ) frame .retain ();
169- handshaker .close (ctx .channel (), close );
170- // Pass on to the rest of the channel
171- ctx .fireChannelRead (close );
168+ try {
169+ CloseWebSocketFrame close = (CloseWebSocketFrame ) frame .retain ();
170+ handshaker .close (ctx .channel (), close );
171+ // Pass on to the rest of the channel
172+ ctx .fireChannelRead (close );
173+ } finally {
174+ // set null to ensure we do not send another close
175+ ctx .channel ().attr (key ).set (null );
176+ }
172177 } else if (frame instanceof PingWebSocketFrame ) {
173178 ctx .write (new PongWebSocketFrame (frame .isFinalFragment (), frame .rsv (), frame .content ()));
174179 } else if (frame instanceof PongWebSocketFrame ) {
@@ -187,7 +192,7 @@ private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame fram
187192 @ Override
188193 public void exceptionCaught (ChannelHandlerContext ctx , Throwable cause ) {
189194 try {
190- Consumer <Message > consumer = ctx .channel ().attr (key ).get ( );
195+ Consumer <Message > consumer = ctx .channel ().attr (key ).getAndSet ( null );
191196
192197 if (consumer != null ) {
193198 byte [] reason = Objects .toString (cause ).getBytes (UTF_8 );
@@ -201,12 +206,29 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
201206 try {
202207 consumer .accept (new CloseMessage (1011 , new String (reason , UTF_8 )));
203208 } catch (Exception ex ) {
204- LOG .log (Level .FINE , "failed to send the close message" , ex );
209+ LOG .log (Level .FINE , "failed to send the close message, code: 1011 " , ex );
205210 }
206211 }
207212 } finally {
208213 LOG .log (Level .FINE , "exception caught, close the context" , cause );
209214 ctx .close ();
210215 }
211216 }
217+
218+ @ Override
219+ public void channelInactive (ChannelHandlerContext ctx ) throws Exception {
220+ try {
221+ super .channelInactive (ctx );
222+ } finally {
223+ Consumer <Message > consumer = ctx .channel ().attr (key ).getAndSet (null );
224+
225+ if (consumer != null ) {
226+ try {
227+ consumer .accept (new CloseMessage (1001 , "channel got inactive" ));
228+ } catch (Exception ex ) {
229+ LOG .log (Level .FINE , "failed to send the close message, code: 1001" , ex );
230+ }
231+ }
232+ }
233+ }
212234}
0 commit comments