Permalink
Browse files

Better error handling for 'special processes'

  • Loading branch information...
1 parent 7815a88 commit 0a3d64f0789d2ead1f123e37fd7bfdb14109df26 @Vagabond Vagabond committed Apr 23, 2012
Showing with 67 additions and 16 deletions.
  1. +12 −8 src/error_logger_lager_h.erl
  2. +47 −8 test/lager_test_backend.erl
  3. +8 −0 test/special_process.erl
@@ -161,15 +161,14 @@ format_crash_report(Report, Neighbours) ->
proplists:get_value(pid, Report);
Atom -> Atom
end,
- {_Class, Reason, Trace} = proplists:get_value(error_info, Report),
- ReasonStr = case is_atom(Reason) of
- true ->
- format_reason({Reason, Trace});
- _ ->
- format_reason(Reason)
+ {Class, Reason, Trace} = proplists:get_value(error_info, Report),
+ ReasonStr = format_reason({Reason, Trace}),
+ Type = case Class of
+ exit -> "exited";
+ _ -> "crashed"
end,
- io_lib:format("Process ~w with ~w neighbours crashed with reason: ~s",
- [Name, length(Neighbours), ReasonStr]).
+ io_lib:format("Process ~w with ~w neighbours ~s with reason: ~s",
+ [Name, length(Neighbours), Type, ReasonStr]).
format_offender(Off) ->
case proplists:get_value(mfargs, Off) of
@@ -254,6 +253,11 @@ format_reason({noproc, MFA}) ->
["no such process or port in call to ", format_mfa(MFA)];
format_reason({{badfun, Term}, [MFA|_]}) ->
["bad function ", print_val(Term), " in ", format_mfa(MFA)];
+format_reason({Reason, [{M, F, A}|_]}) when is_atom(M), is_atom(F), is_integer(A) ->
+ [format_reason(Reason), " in ", format_mfa({M, F, A})];
+format_reason({Reason, [{M, F, A, Props}|_]}) when is_atom(M), is_atom(F), is_integer(A), is_list(Props) ->
+ %% line numbers
+ [format_reason(Reason), " in ", format_mfa({M, F, A, Props})];
format_reason(Reason) ->
{Str, _} = lager_trunc_io:print(Reason, 500),
Str.
@@ -655,7 +655,7 @@ error_logger_redirect_test_() ->
},
{"crash report for emfile",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, {emfile, [{stack, trace, 1}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, emfile, [{stack, trace, 1}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: maximum number of file descriptors exhausted, check ulimit -n", [self(), self()])),
@@ -664,7 +664,7 @@ error_logger_redirect_test_() ->
},
{"crash report for system process limit",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, {system_limit, [{erlang, spawn, 1}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, system_limit, [{erlang, spawn, 1}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of processes exceeded", [self(), self()])),
@@ -673,7 +673,7 @@ error_logger_redirect_test_() ->
},
{"crash report for system process limit2",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, {system_limit, [{erlang, spawn_opt, 1}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, system_limit, [{erlang, spawn_opt, 1}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of processes exceeded", [self(), self()])),
@@ -682,7 +682,7 @@ error_logger_redirect_test_() ->
},
{"crash report for system port limit",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, {system_limit, [{erlang, open_port, 1}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, system_limit, [{erlang, open_port, 1}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of ports exceeded", [self(), self()])),
@@ -691,7 +691,7 @@ error_logger_redirect_test_() ->
},
{"crash report for system port limit",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, {system_limit, [{erlang, list_to_atom, 1}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, []}, {error_info, {error, system_limit, [{erlang, list_to_atom, 1}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: tried to create an atom larger than 255, or maximum atom count exceeded", [self(), self()])),
@@ -700,7 +700,7 @@ error_logger_redirect_test_() ->
},
{"crash report for system ets table limit",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, test}, {error_info, {error, {system_limit,[{ets,new,[segment_offsets,[ordered_set,public]]},{mi_segment,open_write,1},{mi_buffer_converter,handle_cast,2},{gen_server,handle_msg,5},{proc_lib,init_p_do_apply,3}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {registered_name, test}, {error_info, {error, system_limit, [{ets,new,[segment_offsets,[ordered_set,public]]},{mi_segment,open_write,1},{mi_buffer_converter,handle_cast,2},{gen_server,handle_msg,5},{proc_lib,init_p_do_apply,3}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
Expected = lists:flatten(io_lib:format("[error] ~w CRASH REPORT Process ~w with 0 neighbours crashed with reason: system limit: maximum number of ETS tables exceeded", [self(), test])),
@@ -709,14 +709,14 @@ error_logger_redirect_test_() ->
},
{"crash report for unknown system limit should be truncated at 500 characters",
fun() ->
- sync_error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, {system_limit,[{wtf,boom,[string:copies("aaaa", 4096)]}]}, []}}], []]),
+ sync_error_logger:error_report(crash_report, [[{pid, self()}, {error_info, {error, system_limit, [{wtf,boom,[string:copies("aaaa", 4096)]}]}}], []]),
_ = gen_event:which_handlers(error_logger),
{_, _, Msg} = pop(),
?assert(length(lists:flatten(Msg)) > 600),
?assert(length(lists:flatten(Msg)) < 650)
end
},
- {"crash reports for 'special processes' should be handled right",
+ {"crash reports for 'special processes' should be handled right - function_clause",
fun() ->
{ok, Pid} = special_process:start(),
unlink(Pid),
@@ -729,6 +729,45 @@ error_logger_redirect_test_() ->
test_body(Expected, lists:flatten(Msg))
end
},
+ {"crash reports for 'special processes' should be handled right - case_clause",
+ fun() ->
+ {ok, Pid} = special_process:start(),
+ unlink(Pid),
+ Pid ! {case_clause, wtf},
+ timer:sleep(500),
+ _ = gen_event:which_handlers(error_logger),
+ {_, _, Msg} = pop(),
+ Expected = lists:flatten(io_lib:format("[error] ~p CRASH REPORT Process ~p with 0 neighbours crashed with reason: no case clause matching wtf in special_process:loop/0",
+ [Pid, Pid])),
+ test_body(Expected, lists:flatten(Msg))
+ end
+ },
+ {"crash reports for 'special processes' should be handled right - exit",
+ fun() ->
+ {ok, Pid} = special_process:start(),
+ unlink(Pid),
+ Pid ! exit,
+ timer:sleep(500),
+ _ = gen_event:which_handlers(error_logger),
+ {_, _, Msg} = pop(),
+ Expected = lists:flatten(io_lib:format("[error] ~p CRASH REPORT Process ~p with 0 neighbours exited with reason: byebye in special_process:loop/0",
+ [Pid, Pid])),
+ test_body(Expected, lists:flatten(Msg))
+ end
+ },
+ {"crash reports for 'special processes' should be handled right - error",
+ fun() ->
+ {ok, Pid} = special_process:start(),
+ unlink(Pid),
+ Pid ! error,
+ timer:sleep(500),
+ _ = gen_event:which_handlers(error_logger),
+ {_, _, Msg} = pop(),
+ Expected = lists:flatten(io_lib:format("[error] ~p CRASH REPORT Process ~p with 0 neighbours crashed with reason: mybad in special_process:loop/0",
+ [Pid, Pid])),
+ test_body(Expected, lists:flatten(Msg))
+ end
+ },
{"messages should not be generated if they don't satisfy the threshold",
fun() ->
lager:set_loglevel(?MODULE, error),
@@ -19,6 +19,14 @@ loop() ->
error ->
erlang:error(mybad),
loop();
+ {case_clause, X} ->
+ case X of
+ notgonnamatch ->
+ ok;
+ notthiseither ->
+ error
+ end,
+ loop();
_ ->
loop()
end.

0 comments on commit 0a3d64f

Please sign in to comment.