Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Better error handling for 'special processes'

  • Loading branch information...
commit 0a3d64f0789d2ead1f123e37fd7bfdb14109df26 1 parent 7815a88
@Vagabond Vagabond authored
View
20 src/error_logger_lager_h.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
@chardan
chardan added a note

Are "Props" always line numbers? Maybe it makes more sense to move this note into format_mfa().

@Vagabond Collaborator

It's just to distinguish the form of the error sent in R15B and later which includes file/line information on where the exception occurred. The previous function clause is for the legacy error form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ [format_reason(Reason), " in ", format_mfa({M, F, A, Props})];
format_reason(Reason) ->
{Str, _} = lager_trunc_io:print(Reason, 500),
Str.
View
55 test/lager_test_backend.erl
@@ -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),
View
8 test/special_process.erl
@@ -19,6 +19,14 @@ loop() ->
error ->
erlang:error(mybad),
loop();
+ {case_clause, X} ->
+ case X of
+ notgonnamatch ->
+ ok;
+ notthiseither ->
+ error
+ end,
+ loop();
_ ->
loop()
end.
Please sign in to comment.
Something went wrong with that request. Please try again.