aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2018-05-28 09:19:49 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2018-05-28 09:19:49 +0300
commit0381ce1e75b07cb8fd0d788de89d106a8a7fb7c7 (patch)
tree96e1be6b30c433cb53ddf4e366a9f4e245167f3a
parentDon't call Mod:function() in xmpp_stream callbacks (diff)
Better report errors of module startup
-rw-r--r--src/gen_mod.erl57
1 files changed, 38 insertions, 19 deletions
diff --git a/src/gen_mod.erl b/src/gen_mod.erl
index ed04767ca..456afca07 100644
--- a/src/gen_mod.erl
+++ b/src/gen_mod.erl
@@ -217,28 +217,13 @@ start_module(Host, Module, Opts0, Order, NeedValidation) ->
try case Module:start(Host, Opts) of
ok -> ok;
{ok, Pid} when is_pid(Pid) -> {ok, Pid};
- Err -> erlang:error(Err)
+ Err -> erlang:error({bad_return, Module, Err})
end
catch Class:Reason ->
ets:delete(ejabberd_modules, {Module, Host}),
- ErrorText =
- case Reason == undef andalso
- code:ensure_loaded(Module) /= {module, Module} of
- true ->
- io_lib:format("Failed to load unknown module "
- "~s for host ~s: make sure "
- "there is no typo and ~s.beam "
- "exists inside either ~s or ~s "
- "directory",
- [Module, Host, Module,
- filename:dirname(code:which(?MODULE)),
- ext_mod:modules_dir()]);
- false ->
- io_lib:format("Problem starting the module ~s for host "
- "~s ~n options: ~p~n ~p: ~p~n~p",
- [Module, Host, Opts, Class, Reason,
- erlang:get_stacktrace()])
- end,
+ ErrorText = format_start_error(
+ Module, Opts, Class, Reason,
+ erlang:get_stacktrace()),
?CRITICAL_MSG(ErrorText, []),
maybe_halt_ejabberd(),
erlang:raise(Class, Reason, erlang:get_stacktrace())
@@ -722,6 +707,40 @@ get_submodules(Host, Module, Opts) ->
[]
end.
+-spec format_start_error(atom(), opts(),
+ error | exit | throw, any(),
+ [erlang:stack_item()]) -> iolist().
+format_start_error(Module, Opts, Class, Reason, St) ->
+ IsLoaded = code:ensure_loaded(Module) == {module, Module},
+ IsStartExported = erlang:function_exported(Module, start, 2),
+ case {Class, Reason} of
+ {error, undef} when not IsLoaded ->
+ io_lib:format("Failed to load unknown module ~s: "
+ "make sure there is no typo and ~s.beam "
+ "exists inside either ~s or ~s "
+ "directory",
+ [Module, Module,
+ filename:dirname(code:which(?MODULE)),
+ ext_mod:modules_dir()]);
+ {error, undef} when not IsStartExported ->
+ io_lib:format("Failed to load module ~s because "
+ "it doesn't export start/2 callback: "
+ "is it really an ejabberd module?", [Module]);
+ {error, {bad_return, Module, Ret}} ->
+ io_lib:format("Module ~s returned unexpected value during "
+ "startup: ~p; this is either not an ejabberd "
+ "module or it implements ejabbed API incorrectly",
+ [Module, Ret]);
+ _ ->
+ io_lib:format("Internal error of module ~s has "
+ "occured during startup:~n"
+ "** Options: ~p~n"
+ "** Class: ~p~n"
+ "** Reason: ~p~n"
+ "** Stacktrace: ~p",
+ [Module, Opts, Class, Reason, St])
+ end.
+
-spec db_type(binary() | global, module()) -> db_type();
(opts(), module()) -> db_type().