summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Klishin <michael@clojurewerkz.org>2020-01-30 19:12:12 +0300
committerMichael Klishin <michael@clojurewerkz.org>2020-01-30 19:12:12 +0300
commit6a4d2721d06b8c70a36e29e6c51bbef6608def55 (patch)
treedef023bec87e22c4c542df1dfd76d28f01c94cf4
parentd621ec907a4b7f33e85e4bc61f10d1c6e1ef0601 (diff)
downloadrabbitmq-server-git-6a4d2721d06b8c70a36e29e6c51bbef6608def55.tar.gz
Override OTP handlers to gracefully shut down on SIGTERM, SIGQUIT
otherwise the default handler will terminate the runtime. Closes #2222. Pair: @vanlightly.
-rw-r--r--src/rabbit.erl6
-rw-r--r--src/rabbit_os_signal_handler.erl57
2 files changed, 63 insertions, 0 deletions
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 35ffc6ea16..0bf6d47700 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -235,6 +235,12 @@
{requires, pre_flight}
]}).
+-rabbit_boot_step({os_signal_handler,
+ [{description, "registers an OS signal handler"},
+ {mfa, {rabbit_sup, start_restartable_child,
+ [rabbit_os_signal_handler]}},
+ {requires, pre_flight}]}).
+
-rabbit_boot_step({direct_client,
[{description, "direct client"},
{mfa, {rabbit_direct, boot, []}},
diff --git a/src/rabbit_os_signal_handler.erl b/src/rabbit_os_signal_handler.erl
new file mode 100644
index 0000000000..df1a421f09
--- /dev/null
+++ b/src/rabbit_os_signal_handler.erl
@@ -0,0 +1,57 @@
+-module(rabbit_os_signal_handler).
+
+-behaviour(gen_event).
+
+-export([start_link/0, init/1,
+ handle_event/2, handle_call/2, handle_info/2,
+ terminate/2]).
+
+%%
+%% API
+%%
+
+start_link() ->
+ rabbit_log:info("Swapping OS signal event handler (erl_signal_server) for our own"),
+ %% delete any previous incarnations, otherwise we would be accumulating
+ %% handlers
+ _ = gen_event:delete_handler(erl_signal_server, ?MODULE, []),
+ %% swap the standard OTP signal handler if there is one
+ ok = gen_event:swap_sup_handler(
+ erl_signal_server,
+ %% what to swap
+ {erl_signal_handler, []},
+ %% new event handler
+ {?MODULE, []}),
+ gen_event:start_link({local, ?MODULE}).
+
+init(_) ->
+ {ok, #{}}.
+
+handle_event(sigterm, State) ->
+ rabbit_log:info("Received a SIGTERM, will shut down gracefully"),
+ rabbit:stop_and_halt(),
+ {ok, State};
+handle_event(sigquit, State) ->
+ rabbit_log:info("Received a SIGQUIT, will shut down gracefully"),
+ rabbit:stop_and_halt(),
+ {ok, State};
+handle_event(sigusr1, State) ->
+ rabbit_log:info("Received a SIGUSR1, ignoring it"),
+ {ok, State};
+%% note: SIGHUP can/will be handled by shells and process managers
+handle_event(sighup, State) ->
+ rabbit_log:info("Received a SIGHUP, ignoring it"),
+ {ok, State};
+handle_event(Msg, S) ->
+ %% delegate all unknown events to the default OTP signal handler
+ erl_signal_handler:handle_event(Msg, S),
+ {ok, S}.
+
+handle_info(_, State) ->
+ {ok, State}.
+
+handle_call(_Request, State) ->
+ {ok, ok, State}.
+
+terminate(_Args, _State) ->
+ ok.