summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/rabbitmq_prelaunch/src/rabbit_prelaunch.erl3
-rw-r--r--apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl85
-rwxr-xr-xscripts/rabbitmq-server11
-rw-r--r--src/rabbit.erl6
-rw-r--r--src/rabbit_os_signal_handler.erl60
5 files changed, 97 insertions, 68 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.
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server
index 5939c845d2..0976c5566a 100755
--- a/scripts/rabbitmq-server
+++ b/scripts/rabbitmq-server
@@ -141,7 +141,9 @@ else
# Signal handlers. They all stop RabbitMQ properly, using
# rabbitmqctl stop. This script will exit with different exit codes:
- # SIGHUP SIGTERM SIGTSTP
+ # SIGHUP, SIGTSTP + SIGCONT
+ # Ignored until we implement a useful behavior.
+ # SIGTERM
# Exits 0 since this is considered a normal process termination.
# SIGINT
# Exits 128 + $signal_number where $signal_number is 2 for SIGINT (see
@@ -150,7 +152,12 @@ else
# don't need to specify this exit code because the shell propagates it.
# Unfortunately, the signal handler doesn't work as expected in Dash,
# thus we need to explicitly restate the exit code.
- trap "stop_rabbitmq_server; exit 0" HUP TERM TSTP
+ #
+ # The behaviors below should remain consistent with the
+ # equivalent signal handlers in the Erlang code
+ # (see apps/rabbitmq_prelaunch/src/rabbit_prelaunch_sighandler.erl).
+ trap '' HUP TSTP CONT
+ trap "stop_rabbitmq_server; exit 0" TERM
trap "stop_rabbitmq_server; exit 130" INT
start_rabbitmq_server "$@" &
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 0f98e50504..12b12bb222 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -235,12 +235,6 @@
{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
deleted file mode 100644
index d221143379..0000000000
--- a/src/rabbit_os_signal_handler.erl
+++ /dev/null
@@ -1,60 +0,0 @@
--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};
-handle_event(sigusr2, State) ->
- rabbit_log:info("Received a SIGUSR2, 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.