1
0
Fork 0
mirror of https://github.com/processone/ejabberd synced 2025-10-03 17:59:31 +02:00

gen_mod: Add support to prepare module stopping before actually stopping any module

Follows the reasoning of application:prep_stop, but applied to gen_mod:
  https://www.erlang.org/docs/28/apps/kernel/application.html#c:prep_stop/1
This commit is contained in:
Badlop 2025-06-26 12:33:48 +02:00
parent 4a51bf90ab
commit 3d89c9199c
2 changed files with 39 additions and 2 deletions

View file

@ -109,6 +109,7 @@ prep_stop(State) ->
ejabberd_service:stop(), ejabberd_service:stop(),
ejabberd_s2s:stop(), ejabberd_s2s:stop(),
ejabberd_system_monitor:stop(), ejabberd_system_monitor:stop(),
gen_mod:prep_stop(),
gen_mod:stop(), gen_mod:stop(),
State. State.

View file

@ -27,7 +27,7 @@
-author('alexey@process-one.net'). -author('alexey@process-one.net').
-export([init/1, start_link/0, start_child/3, start_child/4, -export([init/1, start_link/0, start_child/3, start_child/4,
stop_child/1, stop_child/2, stop/0, config_reloaded/0]). stop_child/1, stop_child/2, prep_stop/0, stop/0, config_reloaded/0]).
-export([start_module/2, stop_module/2, stop_module_keep_config/2, -export([start_module/2, stop_module/2, stop_module_keep_config/2,
get_opt/2, set_opt/3, get_opt_hosts/1, is_equal_opt/3, get_opt/2, set_opt/3, get_opt_hosts/1, is_equal_opt/3,
get_module_opt/3, get_module_opts/2, get_module_opt_hosts/2, get_module_opt/3, get_module_opts/2, get_module_opt_hosts/2,
@ -76,6 +76,7 @@
-callback start(binary(), opts()) -> -callback start(binary(), opts()) ->
ok | {ok, pid()} | ok | {ok, pid()} |
{ok, [registration()]} | {error, term()}. {ok, [registration()]} | {error, term()}.
-callback prep_stop(binary()) -> any().
-callback stop(binary()) -> any(). -callback stop(binary()) -> any().
-callback reload(binary(), opts(), opts()) -> ok | {ok, pid()} | {error, term()}. -callback reload(binary(), opts(), opts()) -> ok | {ok, pid()} | {error, term()}.
-callback mod_opt_type(atom()) -> econf:validator(). -callback mod_opt_type(atom()) -> econf:validator().
@ -86,7 +87,7 @@
example => [string()] | [{binary(), [string()]}]}. example => [string()] | [{binary(), [string()]}]}.
-callback depends(binary(), opts()) -> [{module(), hard | soft}]. -callback depends(binary(), opts()) -> [{module(), hard | soft}].
-optional_callbacks([mod_opt_type/1, reload/3]). -optional_callbacks([mod_opt_type/1, reload/3, prep_stop/1]).
-export_type([opts/0]). -export_type([opts/0]).
-export_type([db_type/0]). -export_type([db_type/0]).
@ -114,6 +115,10 @@ init([]) ->
{read_concurrency, true}]), {read_concurrency, true}]),
{ok, {{one_for_one, 10, 1}, []}}. {ok, {{one_for_one, 10, 1}, []}}.
-spec prep_stop() -> ok.
prep_stop() ->
prep_stop_modules().
-spec stop() -> ok. -spec stop() -> ok.
stop() -> stop() ->
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 60), ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 60),
@ -301,6 +306,21 @@ is_app_running(AppName) ->
lists:keymember(AppName, 1, lists:keymember(AppName, 1,
application:which_applications(Timeout)). application:which_applications(Timeout)).
-spec prep_stop_modules() -> ok.
prep_stop_modules() ->
lists:foreach(
fun(Host) ->
prep_stop_modules(Host)
end, ejabberd_option:hosts()).
-spec prep_stop_modules(binary()) -> ok.
prep_stop_modules(Host) ->
Modules = lists:reverse(loaded_modules_with_opts(Host)),
lists:foreach(
fun({Module, _Args}) ->
prep_stop_module_keep_config(Host, Module)
end, Modules).
-spec stop_modules() -> ok. -spec stop_modules() -> ok.
stop_modules() -> stop_modules() ->
lists:foreach( lists:foreach(
@ -320,6 +340,22 @@ stop_modules(Host) ->
stop_module(Host, Module) -> stop_module(Host, Module) ->
stop_module_keep_config(Host, Module). stop_module_keep_config(Host, Module).
-spec prep_stop_module_keep_config(binary(), atom()) -> error | ok.
prep_stop_module_keep_config(Host, Module) ->
?DEBUG("Preparing to stop ~ts at ~ts", [Module, Host]),
try Module:prep_stop(Host) of
_ ->
ok
catch ?EX_RULE(error, undef, _St) ->
ok;
?EX_RULE(Class, Reason, St) ->
StackTrace = ?EX_STACK(St),
?ERROR_MSG("Failed to prepare stop module ~ts at ~ts:~n** ~ts",
[Module, Host,
misc:format_exception(2, Class, Reason, StackTrace)]),
error
end.
-spec stop_module_keep_config(binary(), atom()) -> error | ok. -spec stop_module_keep_config(binary(), atom()) -> error | ok.
stop_module_keep_config(Host, Module) -> stop_module_keep_config(Host, Module) ->
?DEBUG("Stopping ~ts at ~ts", [Module, Host]), ?DEBUG("Stopping ~ts at ~ts", [Module, Host]),