summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app_utils.erl41
-rw-r--r--src/rabbit.erl42
2 files changed, 56 insertions, 27 deletions
diff --git a/src/app_utils.erl b/src/app_utils.erl
index 4bef83a53e..fdf6ed410f 100644
--- a/src/app_utils.erl
+++ b/src/app_utils.erl
@@ -15,17 +15,21 @@
%%
-module(app_utils).
--export([load_applications/1, start_applications/1,
- stop_applications/1, app_dependency_order/2,
+-export([load_applications/1, start_applications/1, start_applications/2,
+ stop_applications/1, stop_applications/2, app_dependency_order/2,
wait_for_applications/1]).
-ifdef(use_specs).
--spec load_applications([atom()]) -> 'ok'.
--spec start_applications([atom()]) -> 'ok'.
--spec stop_applications([atom()]) -> 'ok'.
--spec wait_for_applications([atom()]) -> 'ok'.
--spec app_dependency_order([atom()], boolean()) -> [digraph:vertex()].
+-type error_handler() :: fun((atom(), any()) -> 'ok').
+
+-spec load_applications([atom()]) -> 'ok'.
+-spec start_applications([atom()]) -> 'ok'.
+-spec stop_applications([atom()]) -> 'ok'.
+-spec start_applications([atom()], error_handler()) -> 'ok'.
+-spec stop_applications([atom()], error_handler()) -> 'ok'.
+-spec wait_for_applications([atom()]) -> 'ok'.
+-spec app_dependency_order([atom()], boolean()) -> [digraph:vertex()].
-endif.
@@ -37,21 +41,34 @@ load_applications(Apps) ->
ok.
start_applications(Apps) ->
+ start_applications(
+ Apps, fun (App, Reason) ->
+ throw({error, {cannot_start_application, App, Reason}})
+ end).
+
+stop_applications(Apps) ->
+ stop_applications(
+ Apps, fun (App, Reason) ->
+ throw({error, {cannot_stop_application, App, Reason}})
+ end).
+
+start_applications(Apps, ErrorHandler) ->
manage_applications(fun lists:foldl/3,
fun application:start/1,
fun application:stop/1,
already_started,
- cannot_start_application,
+ ErrorHandler,
Apps).
-stop_applications(Apps) ->
+stop_applications(Apps, ErrorHandler) ->
manage_applications(fun lists:foldr/3,
fun application:stop/1,
fun application:start/1,
not_started,
- cannot_stop_application,
+ ErrorHandler,
Apps).
+
wait_for_applications(Apps) ->
[wait_for_application(App) || App <- Apps], ok.
@@ -107,14 +124,14 @@ app_dependencies(App) ->
{ok, Lst} -> Lst
end.
-manage_applications(Iterate, Do, Undo, SkipError, ErrorTag, Apps) ->
+manage_applications(Iterate, Do, Undo, SkipError, ErrorHandler, Apps) ->
Iterate(fun (App, Acc) ->
case Do(App) of
ok -> [App | Acc];
{error, {SkipError, _}} -> Acc;
{error, Reason} ->
lists:foreach(Undo, Acc),
- throw({error, {ErrorTag, App, Reason}})
+ ErrorHandler(App, Reason)
end
end, [], Apps),
ok.
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 7a021e378d..e958784197 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -303,7 +303,8 @@ start() ->
ok = rabbit_node_monitor:prepare_cluster_status_files(),
ok = rabbit_mnesia:check_cluster_consistency(),
ok = ensure_working_log_handlers(),
- ok = app_utils:start_applications(app_startup_order()),
+ ok = app_utils:start_applications(
+ app_startup_order(), fun handle_app_error/2),
ok = print_plugin_info(rabbit_plugins:active())
end).
@@ -323,10 +324,17 @@ boot() ->
ok = app_utils:load_applications(ToBeLoaded),
StartupApps = app_utils:app_dependency_order(ToBeLoaded,
false),
- ok = app_utils:start_applications(StartupApps),
+ ok = app_utils:start_applications(
+ StartupApps, fun handle_app_error/2),
ok = print_plugin_info(Plugins)
end).
+handle_app_error(App, {bad_return, {_MFA, {'EXIT', {Reason, _}}}}) ->
+ boot_error({could_not_start, App, Reason}, not_available);
+
+handle_app_error(App, Reason) ->
+ boot_error({could_not_start, App, Reason}, not_available).
+
start_it(StartFun) ->
try
StartFun()
@@ -450,7 +458,7 @@ run_boot_step({StepName, Attributes}) ->
[try
apply(M,F,A)
catch
- _:Reason -> boot_step_error(Reason, erlang:get_stacktrace())
+ _:Reason -> boot_error(Reason, erlang:get_stacktrace())
end || {M,F,A} <- MFAs],
io:format("done~n"),
ok
@@ -489,14 +497,14 @@ sort_boot_steps(UnsortedSteps) ->
{mfa, {M,F,A}} <- Attributes,
not erlang:function_exported(M, F, length(A))] of
[] -> SortedSteps;
- MissingFunctions -> boot_error(
+ MissingFunctions -> basic_boot_error(
"Boot step functions not exported: ~p~n",
[MissingFunctions])
end;
{error, {vertex, duplicate, StepName}} ->
- boot_error("Duplicate boot step name: ~w~n", [StepName]);
+ basic_boot_error("Duplicate boot step name: ~w~n", [StepName]);
{error, {edge, Reason, From, To}} ->
- boot_error(
+ basic_boot_error(
"Could not add boot step dependency of ~w on ~w:~n~s",
[To, From,
case Reason of
@@ -510,7 +518,7 @@ sort_boot_steps(UnsortedSteps) ->
end])
end.
-boot_step_error({error, {timeout_waiting_for_tables, _}}, _Stacktrace) ->
+boot_error({error, {timeout_waiting_for_tables, _}}, _Stacktrace) ->
AllNodes = rabbit_mnesia:all_clustered_nodes(),
{Err, Nodes} =
case AllNodes -- [node()] of
@@ -521,15 +529,19 @@ boot_step_error({error, {timeout_waiting_for_tables, _}}, _Stacktrace) ->
"Timeout contacting cluster nodes: ~p.~n", [Ns]),
Ns}
end,
- boot_error(Err ++ rabbit_nodes:diagnostics(Nodes) ++ "~n~n", []);
-
-boot_step_error(Reason, Stacktrace) ->
- boot_error("Error description:~n ~p~n~n"
- "Log files (may contain more information):~n ~s~n ~s~n~n"
- "Stack trace:~n ~p~n~n",
- [Reason, log_location(kernel), log_location(sasl), Stacktrace]).
+ basic_boot_error(Err ++ rabbit_nodes:diagnostics(Nodes) ++ "~n~n", []);
+
+boot_error(Reason, Stacktrace) ->
+ Fmt = "Error description:~n ~p~n~n"
+ "Log files (may contain more information):~n ~s~n ~s~n~n",
+ Args = [Reason, log_location(kernel), log_location(sasl)],
+ case Stacktrace of
+ not_available -> basic_boot_error(Fmt, Args);
+ _ -> basic_boot_error(Fmt ++ "Stack trace:~n ~p~n~n",
+ Args ++ [Stacktrace])
+ end.
-boot_error(Format, Args) ->
+basic_boot_error(Format, Args) ->
io:format("~n~nBOOT FAILED~n===========~n~n" ++ Format, Args),
error_logger:error_msg(Format, Args),
timer:sleep(1000),