diff options
| -rw-r--r-- | src/app_utils.erl | 41 | ||||
| -rw-r--r-- | src/rabbit.erl | 42 |
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), |
