aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd.erl')
-rw-r--r--src/ejabberd.erl63
1 files changed, 40 insertions, 23 deletions
diff --git a/src/ejabberd.erl b/src/ejabberd.erl
index a7de9ab11..f7157f61d 100644
--- a/src/ejabberd.erl
+++ b/src/ejabberd.erl
@@ -38,7 +38,7 @@
-protocol({xep, 270, '1.0'}).
-export([start/0, stop/0, halt/0, start_app/1, start_app/2,
- get_pid_file/0, check_app/1, module_name/1, is_loaded/0]).
+ get_pid_file/0, check_apps/0, module_name/1, is_loaded/0]).
-include("logger.hrl").
@@ -49,8 +49,8 @@ stop() ->
application:stop(ejabberd).
halt() ->
- application:stop(lager),
- application:stop(sasl),
+ _ = application:stop(lager),
+ _ = application:stop(sasl),
erlang:halt(1, [{flush, true}]).
%% @spec () -> false | string()
@@ -71,21 +71,15 @@ start_app(App, Type) ->
StartFlag = not is_loaded(),
start_app(App, Type, StartFlag).
-check_app(App) ->
- StartFlag = not is_loaded(),
- spawn(fun() -> check_app_modules(App, StartFlag) end),
- ok.
-
is_loaded() ->
Apps = application:which_applications(),
lists:keymember(ejabberd, 1, Apps).
-start_app(App, Type, StartFlag) when not is_list(App) ->
+start_app(App, Type, StartFlag) when is_atom(App) ->
start_app([App], Type, StartFlag);
start_app([App|Apps], Type, StartFlag) ->
case application:start(App,Type) of
ok ->
- spawn(fun() -> check_app_modules(App, StartFlag) end),
start_app(Apps, Type, StartFlag);
{error, {already_started, _}} ->
start_app(Apps, Type, StartFlag);
@@ -93,23 +87,23 @@ start_app([App|Apps], Type, StartFlag) ->
case lists:member(DepApp, [App|Apps]) of
true ->
Reason = io_lib:format(
- "failed to start application '~p': "
- "circular dependency on '~p' detected",
+ "Failed to start Erlang application '~s': "
+ "circular dependency with '~s' detected",
[App, DepApp]),
exit_or_halt(Reason, StartFlag);
false ->
start_app([DepApp,App|Apps], Type, StartFlag)
end;
- Err ->
- Reason = io_lib:format("failed to start application '~p': ~p",
- [App, Err]),
+ {error, Why} ->
+ Reason = io_lib:format(
+ "Failed to start Erlang application '~s': ~s. ~s",
+ [App, format_error(Why), hint()]),
exit_or_halt(Reason, StartFlag)
end;
start_app([], _Type, _StartFlag) ->
ok.
check_app_modules(App, StartFlag) ->
- sleep(5000),
case application:get_key(App, modules) of
{ok, Mods} ->
lists:foreach(
@@ -118,12 +112,12 @@ check_app_modules(App, StartFlag) ->
non_existing ->
File = get_module_file(App, Mod),
Reason = io_lib:format(
- "couldn't find module ~s "
- "needed for application '~p'",
- [File, App]),
+ "Couldn't find file ~s needed "
+ "for Erlang application '~s'. ~s",
+ [File, App, hint()]),
exit_or_halt(Reason, StartFlag);
_ ->
- sleep(10)
+ ok
end
end, Mods);
_ ->
@@ -131,6 +125,23 @@ check_app_modules(App, StartFlag) ->
ok
end.
+check_apps() ->
+ spawn(
+ fun() ->
+ Apps = [ejabberd |
+ [App || {App, _, _} <- application:which_applications(),
+ App /= ejabberd]],
+ ?DEBUG("Checking consistency of applications: ~s",
+ [misc:join_atoms(Apps, <<", ">>)]),
+ misc:peach(
+ fun(App) ->
+ check_app_modules(App, true)
+ end, Apps),
+ ?DEBUG("All applications are intact", []),
+ lists:foreach(fun erlang:garbage_collect/1, processes())
+ end).
+
+-spec exit_or_halt(iodata(), boolean()) -> no_return().
exit_or_halt(Reason, StartFlag) ->
?CRITICAL_MSG(Reason, []),
if StartFlag ->
@@ -140,9 +151,6 @@ exit_or_halt(Reason, StartFlag) ->
erlang:error(application_start_failed)
end.
-sleep(N) ->
- timer:sleep(p1_rand:uniform(N)).
-
get_module_file(App, Mod) ->
BaseName = atom_to_list(Mod),
case code:lib_dir(App, ebin) of
@@ -177,3 +185,12 @@ erlang_name(Atom) when is_atom(Atom) ->
misc:atom_to_binary(Atom);
erlang_name(Bin) when is_binary(Bin) ->
Bin.
+
+format_error({Reason, File}) when is_list(Reason), is_list(File) ->
+ Reason ++ ": " ++ File;
+format_error(Term) ->
+ io_lib:format("~p", [Term]).
+
+hint() ->
+ "This usually means that ejabberd or Erlang "
+ "was compiled/installed incorrectly.".