From c1490d7d5503636e7995583222cf8edf5f882db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 8 Jan 2024 11:44:34 +0100 Subject: Ensure HTTP/1.1 Websocket resets the trap_exit flag While we are identified as a supervisor in the tree, we no longer manage children processes at that point, so do not need to trap exit signals. Users can still enable trap_exit if they prefer to. --- doc/src/manual/cowboy_websocket.asciidoc | 1 + src/cowboy_http.erl | 4 +++- test/handlers/ws_init_h.erl | 5 ++++- test/ws_SUITE.erl | 1 + test/ws_handler_SUITE.erl | 8 ++++++++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/cowboy_websocket.asciidoc b/doc/src/manual/cowboy_websocket.asciidoc index df74507..b1eb593 100644 --- a/doc/src/manual/cowboy_websocket.asciidoc +++ b/doc/src/manual/cowboy_websocket.asciidoc @@ -285,6 +285,7 @@ normal circumstances if necessary. == Changelog +* *2.11*: HTTP/1.1 Websocket no longer traps exits by default. * *2.8*: The `active_n` option was added. * *2.7*: The commands based interface has been documented. The old interface is now deprecated. diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 70f8268..33ad7af 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -1212,11 +1212,13 @@ commands(State0=#state{ref=Ref, parent=Parent, socket=Socket, transport=Transpor _ -> State end, #stream{state=StreamState} = lists:keyfind(StreamID, #stream.id, Streams), - %% @todo We need to shutdown processes here first. stream_call_terminate(StreamID, switch_protocol, StreamState, State), %% Terminate children processes and flush any remaining messages from the mailbox. cowboy_children:terminate(Children), flush(Parent), + %% Turn off the trap_exit process flag + %% since this process will no longer be a supervisor. + process_flag(trap_exit, false), Protocol:takeover(Parent, Ref, Socket, Transport, Opts, Buffer, InitialState); %% Set options dynamically. commands(State0=#state{overriden_opts=Opts}, diff --git a/test/handlers/ws_init_h.erl b/test/handlers/ws_init_h.erl index db5307b..bbe9ef9 100644 --- a/test/handlers/ws_init_h.erl +++ b/test/handlers/ws_init_h.erl @@ -36,7 +36,10 @@ do_websocket_init(State=reply_many_hibernate) -> do_websocket_init(State=reply_many_close) -> {[{text, "Hello"}, close], State}; do_websocket_init(State=reply_many_close_hibernate) -> - {[{text, "Hello"}, close], State, hibernate}. + {[{text, "Hello"}, close], State, hibernate}; +do_websocket_init(State=reply_trap_exit) -> + Text = "trap_exit: " ++ atom_to_list(element(2, process_info(self(), trap_exit))), + {[{text, Text}, close], State, hibernate}. websocket_handle(_, State) -> {[], State}. diff --git a/test/ws_SUITE.erl b/test/ws_SUITE.erl index 9abeaca..126d8c6 100644 --- a/test/ws_SUITE.erl +++ b/test/ws_SUITE.erl @@ -341,6 +341,7 @@ ws_first_frame_with_handshake(Config) -> {ok, <<1:1, 0:3, 1:4, 0:1, 5:7, "Hello">>} = gen_tcp:recv(Socket, 0, 6000), ok. +%% @todo Move these tests to ws_handler_SUITE. ws_init_return_ok(Config) -> doc("Handler does nothing."), {ok, Socket, _} = do_handshake("/ws_init?ok", Config), diff --git a/test/ws_handler_SUITE.erl b/test/ws_handler_SUITE.erl index 435600f..362b03a 100644 --- a/test/ws_handler_SUITE.erl +++ b/test/ws_handler_SUITE.erl @@ -50,6 +50,7 @@ init_dispatch(Name) -> {"/init", ws_init_commands_h, RunOrHibernate}, {"/handle", ws_handle_commands_h, RunOrHibernate}, {"/info", ws_info_commands_h, RunOrHibernate}, + {"/trap_exit", ws_init_h, RunOrHibernate}, {"/active", ws_active_commands_h, RunOrHibernate}, {"/deflate", ws_deflate_commands_h, RunOrHibernate}, {"/set_options", ws_set_options_commands_h, RunOrHibernate}, @@ -211,6 +212,13 @@ do_many_frames_then_close_frame(Config, Path) -> {ok, close} = receive_ws(ConnPid, StreamRef), gun_down(ConnPid). +websocket_init_trap_exit_false(Config) -> + doc("The trap_exit process flag must be set back to false before " + "the connection is taken over by Websocket."), + {ok, ConnPid, StreamRef} = gun_open_ws(Config, "/trap_exit?reply_trap_exit", []), + {ok, {text, <<"trap_exit: false">>}} = receive_ws(ConnPid, StreamRef), + ok. + websocket_active_false(Config) -> doc("The {active, false} command stops receiving data from the socket. " "The {active, true} command reenables it."), -- cgit v1.2.3