summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl3
-rw-r--r--apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl85
2 files changed, 88 insertions, 0 deletions
diff --git a/apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl b/apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl
index b564fadf51..ef15f47a75 100644
--- a/apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl
+++ b/apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl
@@ -48,6 +48,9 @@ do_run() ->
%% Configure dbg if requested.
rabbit_prelaunch_early_logging:enable_quick_dbg(rabbit_env:dbg_config()),
+ %% Setup signal handler.
+ ok = rabbit_prelaunch_sighandler:setup(),
+
%% We assert Mnesia is stopped before we run the prelaunch
%% phases.
%%
diff --git a/apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl b/apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl
new file mode 100644
index 0000000000..a6b5d3c2f7
--- /dev/null
+++ b/apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl
@@ -0,0 +1,85 @@
+-module(rabbit_prelaunch_sighandler).
+-behaviour(gen_event).
+
+-export([setup/0,
+ init/1,
+ handle_event/2,
+ handle_call/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% CAUTION: Signal handling in this module must be kept consistent
+%% with the same handling in rabbitmq-server(8).
+
+%% #{signal => default | ignore | stop}.
+-define(SIGNALS_HANDLED_BY_US,
+ #{
+ %% SIGHUP is often used to reload the configuration or reopen
+ %% log files after they were rotated. We don't support any
+ %% of those two cases, so ignore it for now, until we can do
+ %% something about it.
+ sighup => ignore,
+
+ %% SIGTSTP is triggered by Ctrl+Z to pause a program. However
+ %% we can't handle SIGCONT, the signal used to resume the
+ %% program. Unfortunately, it makes a SIGTSTP handler less
+ %% useful here.
+ sigtstp => ignore
+ }).
+
+-define(SIGNAL_HANDLED_BY_ERLANG(Signal),
+ Signal =:= sigusr1 orelse
+ Signal =:= sigquit orelse
+ Signal =:= sigterm).
+
+-define(SERVER, erl_signal_server).
+
+setup() ->
+ case whereis(?SERVER) of
+ undefined ->
+ ok;
+ _ ->
+ case lists:member(?MODULE, gen_event:which_handlers(?SERVER)) of
+ true -> ok;
+ false -> gen_event:add_handler(?SERVER, ?MODULE, [])
+ end
+ end.
+
+init(_Args) ->
+ maps:fold(
+ fun
+ (Signal, _, Ret) when ?SIGNAL_HANDLED_BY_ERLANG(Signal) -> Ret;
+ (Signal, default, ok) -> os:set_signal(Signal, default);
+ (Signal, ignore, ok) -> os:set_signal(Signal, ignore);
+ (Signal, _, ok) -> os:set_signal(Signal, handle)
+ end, ok, ?SIGNALS_HANDLED_BY_US),
+ {ok, #{}}.
+
+handle_event(Signal, State) when ?SIGNAL_HANDLED_BY_ERLANG(Signal) ->
+ {ok, State};
+handle_event(Signal, State) ->
+ case ?SIGNALS_HANDLED_BY_US of
+ #{Signal := stop} ->
+ error_logger:info_msg(
+ "~s received - shutting down~n",
+ [string:uppercase(atom_to_list(Signal))]),
+ ok = init:stop();
+ _ ->
+ error_logger:info_msg(
+ "~s received - unhandled signal~n",
+ [string:uppercase(atom_to_list(Signal))])
+ end,
+ {ok, State}.
+
+handle_info(_, State) ->
+ {ok, State}.
+
+handle_call(_, State) ->
+ {ok, ok, State}.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+terminate(_Args, _State) ->
+ ok.