Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix for crash on error_logger:error_report(not_std_error, [{a,b}]) #2

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions rebar.config
@@ -0,0 +1,15 @@

{erl_opts, [warn_unused_vars,
warn_export_all,
warn_shadow_vars,
warn_unused_import,
warn_unused_function,
warn_bif_clash,
warn_unused_record,
warn_deprecated_function,
warn_obsolete_guard,
strict_validation,
warn_export_vars,
warn_exported_vars,
warn_missing_spec,
warn_untyped_record, debug_info]}.
3 changes: 3 additions & 0 deletions src/riak_err_app.erl
Expand Up @@ -90,11 +90,14 @@
start/2, start/2,
stop/1]). stop/1]).


-spec start() -> 'ok' | {'error', term()}.
start() -> start() ->
application:start(riak_err). application:start(riak_err).


-spec start(normal | {takeover, node()} | {failover, node()}, term()) -> {ok, pid()}.
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
riak_err_sup:start_link(). riak_err_sup:start_link().


-spec stop([]) -> ok.
stop(_State) -> stop(_State) ->
ok. ok.
32 changes: 19 additions & 13 deletions src/riak_err_handler.erl
Expand Up @@ -52,11 +52,11 @@
code_change/3]). code_change/3]).


-record(state, { -record(state, {
term_max_size, term_max_size :: pos_integer(),
fmt_max_bytes, fmt_max_bytes :: pos_integer(),
log_path, log_path :: undefined | string(),
log_fh, log_fh :: undefined | file:io_device(),
errlog_type errlog_type :: error | progress | all
}). }).


%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
Expand All @@ -65,28 +65,28 @@


%% @doc Add a supervised handler to the OTP kernel's %% @doc Add a supervised handler to the OTP kernel's
%% <tt>error_logger</tt> event server. %% <tt>error_logger</tt> event server.

-spec add_sup_handler() -> term().
add_sup_handler() -> add_sup_handler() ->
gen_event:add_sup_handler(error_logger, ?MODULE, []). gen_event:add_sup_handler(error_logger, ?MODULE, []).


%% @doc Change the internal value of <tt>set_term_max_size</tt>. %% @doc Change the internal value of <tt>set_term_max_size</tt>.

-spec set_term_max_size(pos_integer()) -> ok.
set_term_max_size(Num) -> set_term_max_size(Num) ->
gen_event:call(error_logger, ?MODULE, {set_term_max_size, Num}, infinity). gen_event:call(error_logger, ?MODULE, {set_term_max_size, Num}, infinity).


%% @doc Change the internal value of <tt>set_fmt_max_bytes</tt>. %% @doc Change the internal value of <tt>set_fmt_max_bytes</tt>.

-spec set_fmt_max_bytes(pos_integer()) -> ok.
set_fmt_max_bytes(Num) -> set_fmt_max_bytes(Num) ->
gen_event:call(error_logger, ?MODULE, {set_fmt_max_bytes, Num}, infinity). gen_event:call(error_logger, ?MODULE, {set_fmt_max_bytes, Num}, infinity).


%% @doc Tell our error handler to reopen the <tt>sasl_error_logger</tt> file's %% @doc Tell our error handler to reopen the <tt>sasl_error_logger</tt> file's
%% file handle (e.g., to assist log file rotation schemes). %% file handle (e.g., to assist log file rotation schemes).

-spec reopen_log_file() -> ok.
reopen_log_file() -> reopen_log_file() ->
gen_event:call(error_logger, riak_err_handler, reopen_log_file, infinity). gen_event:call(error_logger, riak_err_handler, reopen_log_file, infinity).


%% @doc Debugging: get internal state record. %% @doc Debugging: get internal state record.

-spec get_state() -> #state{}.
get_state() -> get_state() ->
gen_event:call(error_logger, ?MODULE, {get_state}, infinity). gen_event:call(error_logger, ?MODULE, {get_state}, infinity).


Expand All @@ -99,6 +99,7 @@ get_state() ->
%% Returns: {ok, State} | %% Returns: {ok, State} |
%% Other %% Other
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec init([]) -> {ok, #state{}}.
init([]) -> init([]) ->
TermMaxSize = get_int_env(term_max_size, 10*1024), TermMaxSize = get_int_env(term_max_size, 10*1024),
FmtMaxBytes = get_int_env(fmt_max_bytes, 12*1024), FmtMaxBytes = get_int_env(fmt_max_bytes, 12*1024),
Expand All @@ -125,6 +126,7 @@ init([]) ->
%% {swap_handler, Args1, State1, Mod2, Args2} | %% {swap_handler, Args1, State1, Mod2, Args2} |
%% remove_handler %% remove_handler
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_event({atom(), pid(), {pid(), string() | atom(), any()}}, #state{}) -> {ok, #state{}}.
handle_event(Event, State) -> handle_event(Event, State) ->
Formatted = format_event(Event, State), Formatted = format_event(Event, State),
io:put_chars(Formatted), io:put_chars(Formatted),
Expand All @@ -136,6 +138,7 @@ handle_event(Event, State) ->
%% {swap_handler, Reply, Args1, State1, Mod2, Args2} | %% {swap_handler, Reply, Args1, State1, Mod2, Args2} |
%% {remove_handler, Reply} %% {remove_handler, Reply}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_call(term(), #state{}) -> {ok, ok, #state{}}.
handle_call(reopen_log_file, State) -> handle_call(reopen_log_file, State) ->
case State#state.log_fh of case State#state.log_fh of
undefined -> undefined ->
Expand All @@ -161,6 +164,7 @@ handle_call(_Request, State) ->
%% {swap_handler, Args1, State1, Mod2, Args2} | %% {swap_handler, Args1, State1, Mod2, Args2} |
%% remove_handler %% remove_handler
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_info(term(), #state{}) -> {ok, #state{}}.
handle_info(_Info, State) -> handle_info(_Info, State) ->
{ok, State}. {ok, State}.


Expand All @@ -169,9 +173,11 @@ handle_info(_Info, State) ->
%% Purpose: Shutdown the server %% Purpose: Shutdown the server
%% Returns: any %% Returns: any
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec terminate(term(), #state{}) -> ok.
terminate(_Reason, _State) -> terminate(_Reason, _State) ->
ok. ok.


-spec code_change(term(), #state{}, term()) -> {ok, #state{}}.
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.


Expand Down Expand Up @@ -248,18 +254,18 @@ perhaps_a_sasl_report(error_report, {Pid, Type, Report}, S) ->
{sasl_type_to_report_head(Type), Pid, {sasl_type_to_report_head(Type), Pid,
sasl_limited_str(Type, Report, S), true}; sasl_limited_str(Type, Report, S), true};
false -> false ->
{ignore, ignore, ignore} {ignore, ignore, ignore, false}
end; end;
perhaps_a_sasl_report(info_report, {Pid, Type, Report}, S) -> perhaps_a_sasl_report(info_report, {Pid, Type, Report}, S) ->
case riak_err_stdlib:is_my_info_report(Type) of case riak_err_stdlib:is_my_info_report(Type) of
true -> true ->
{sasl_type_to_report_head(Type), Pid, {sasl_type_to_report_head(Type), Pid,
sasl_limited_str(Type, Report, S), false}; sasl_limited_str(Type, Report, S), false};
false -> false ->
{ignore, ignore, ignore} {ignore, ignore, ignore, false}
end; end;
perhaps_a_sasl_report(_, _, _) -> perhaps_a_sasl_report(_, _, _) ->
{ignore, ignore, ignore}. {ignore, ignore, ignore, false}.


sasl_type_to_report_head(supervisor_report) -> sasl_type_to_report_head(supervisor_report) ->
"SUPERVISOR REPORT"; "SUPERVISOR REPORT";
Expand Down
25 changes: 19 additions & 6 deletions src/riak_err_monitor.erl
Expand Up @@ -31,16 +31,18 @@
code_change/3]). code_change/3]).


-record(state, { -record(state, {
max_len = 20*1024, max_len = 20*1024 :: pos_integer(),
tref tref :: timer:tref()
}). }).


%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% API %%% API
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?NAME}, ?MODULE, [], []). gen_server:start_link({local, ?NAME}, ?MODULE, [], []).


-spec stop() -> ok.
stop() -> stop() ->
gen_event:call(?NAME, stop, infinity). gen_event:call(?NAME, stop, infinity).


Expand All @@ -55,14 +57,18 @@ stop() ->
%% ignore | %% ignore |
%% {stop, Reason} %% {stop, Reason}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec init([]) -> {ok, #state{}}.
init([]) -> init([]) ->
%% Add our custom handler. %% Add our custom handler.
ok = riak_err_handler:add_sup_handler(), ok = riak_err_handler:add_sup_handler(),


%% Disable the default error logger handlers and SASL handlers. %% Disable the default error logger handlers and SASL handlers.
[gen_event:delete_handler(error_logger, Handler, {stop_please, ?MODULE}) || ok = lists:foreach(
Handler <- [error_logger, error_logger_tty_h, sasl_report_tty_h, fun(Handler) ->
sasl_report_file_h]], gen_event:delete_handler(error_logger, Handler, {stop_please, ?MODULE})
end,
[error_logger, error_logger_tty_h, sasl_report_tty_h, sasl_report_file_h]),

{ok, TRef} = timer:send_interval(1000, reopen_log_file), {ok, TRef} = timer:send_interval(1000, reopen_log_file),
{ok, #state{tref = TRef}}. {ok, #state{tref = TRef}}.


Expand All @@ -75,15 +81,19 @@ init([]) ->
%% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, Reply, State} | (terminate/2 is called)
%% {stop, Reason, State} (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called)
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_call(stop | term(), reference(), #state{}) -> {stop, normal, ok, #state{}} | {reply, not_implemented, #state{}}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call(_Request, _From, State) -> handle_call(_Request, _From, State) ->
{reply, not_implemented, State}. {reply, not_implemented, State}.


%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%% Func: handle_cast/2 %% Func: handle_cast/2
%% Returns: {noreply, State} | %% Returns: {noreply, State} |
%% {noreply, State, Timeout} | %% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called)
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_cast(tuple(), #state{}) -> {noreply, #state{}}.
handle_cast(Msg, State) -> handle_cast(Msg, State) ->
{Str, _} = trunc_io:print(Msg, State#state.max_len), {Str, _} = trunc_io:print(Msg, State#state.max_len),
error_logger:error_msg("~w: ~s:handle_cast got ~s\n", error_logger:error_msg("~w: ~s:handle_cast got ~s\n",
Expand All @@ -96,6 +106,7 @@ handle_cast(Msg, State) ->
%% {noreply, State, Timeout} | %% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called)
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec handle_info(reopen_log_file | {gen_event_EXIT, ?MODULE, term()} | tuple(), #state{}) -> {noreply, #state{}} | {stop, gen_event_EXIT, #state{}}.
handle_info(reopen_log_file, State) -> handle_info(reopen_log_file, State) ->
ok = riak_err_handler:reopen_log_file(), ok = riak_err_handler:reopen_log_file(),
{noreply, State}; {noreply, State};
Expand All @@ -122,9 +133,11 @@ handle_info(Info, State) ->
%% Purpose: Shutdown the server %% Purpose: Shutdown the server
%% Returns: any (ignored by gen_server) %% Returns: any (ignored by gen_server)
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
-spec terminate(term(), #state{}) -> ok.
terminate(_Reason, _State) -> terminate(_Reason, _State) ->
ok. ok.


-spec code_change(term(), #state{}, term()) -> {ok, #state{}}.
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.


Expand Down
19 changes: 16 additions & 3 deletions src/riak_err_stdlib.erl
Expand Up @@ -30,16 +30,27 @@
-export([sup_get/2]). -export([sup_get/2]).
-export([proc_lib_format/2]). -export([proc_lib_format/2]).


%% From calendar
-type year1970() :: 1970..10000. % should probably be 1970..
-type month() :: 1..12.
-type day() :: 1..31.
-type hour() :: 0..23.
-type minute() :: 0..59.
-type second() :: 0..59.
-type t_time() :: {hour(),minute(),second()}.
-type t_datetime1970() :: {{year1970(),month(),day()},t_time()}.

%% From OTP stdlib's error_logger_tty_h.erl ... These functions aren't %% From OTP stdlib's error_logger_tty_h.erl ... These functions aren't
%% exported. %% exported.

-spec write_time({utc, t_datetime1970()} | t_datetime1970(), string()) -> string().
write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) -> write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
write_time({{Y,Mo,D},{H,Mi,S}},Type) -> write_time({{Y,Mo,D},{H,Mi,S}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).


-spec maybe_utc(t_datetime1970()) -> {utc, t_datetime1970()} | t_datetime1970().
maybe_utc(Time) -> maybe_utc(Time) ->
UTC = case application:get_env(sasl, utc_log) of UTC = case application:get_env(sasl, utc_log) of
{ok, Val} -> {ok, Val} ->
Expand Down Expand Up @@ -86,14 +97,16 @@ month(12) -> "Dec".


%% From OTP sasl's sasl_report.erl ... These functions aren't %% From OTP sasl's sasl_report.erl ... These functions aren't
%% exported. %% exported.

-spec is_my_error_report(atom()) -> boolean().
is_my_error_report(supervisor_report) -> true; is_my_error_report(supervisor_report) -> true;
is_my_error_report(crash_report) -> true; is_my_error_report(crash_report) -> true;
is_my_error_report(_) -> false. is_my_error_report(_) -> false.


-spec is_my_info_report(atom()) -> boolean().
is_my_info_report(progress) -> true; is_my_info_report(progress) -> true;
is_my_info_report(_) -> false. is_my_info_report(_) -> false.


-spec sup_get(term(), [proplists:property()]) -> term().
sup_get(Tag, Report) -> sup_get(Tag, Report) ->
case lists:keysearch(Tag, 1, Report) of case lists:keysearch(Tag, 1, Report) of
{value, {_, Value}} -> {value, {_, Value}} ->
Expand All @@ -103,7 +116,7 @@ sup_get(Tag, Report) ->
end. end.


%% From OTP stdlib's proc_lib.erl ... These functions aren't exported. %% From OTP stdlib's proc_lib.erl ... These functions aren't exported.

-spec proc_lib_format([term()], pos_integer()) -> string().
proc_lib_format([OwnReport,LinkReport], FmtMaxBytes) -> proc_lib_format([OwnReport,LinkReport], FmtMaxBytes) ->
OwnFormat = format_report(OwnReport, FmtMaxBytes), OwnFormat = format_report(OwnReport, FmtMaxBytes),
LinkFormat = format_report(LinkReport, FmtMaxBytes), LinkFormat = format_report(LinkReport, FmtMaxBytes),
Expand Down
6 changes: 6 additions & 0 deletions src/riak_err_sup.erl
Expand Up @@ -26,9 +26,15 @@


-define(SERVER, ?MODULE). -define(SERVER, ?MODULE).


%% From supervisor
-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.

-spec start_link() -> startlink_ret().
start_link() -> start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []). supervisor:start_link({local, ?SERVER}, ?MODULE, []).


-spec init([]) -> {ok, {{one_for_one, 1000, 3600}, [supervisor:child_spec()]}}.
init([]) -> init([]) ->
RestartStrategy = one_for_one, RestartStrategy = one_for_one,
MaxRestarts = 1000, MaxRestarts = 1000,
Expand Down
10 changes: 9 additions & 1 deletion src/trunc_io.erl
Expand Up @@ -36,6 +36,7 @@


%% @doc Returns an flattened list containing the ASCII representation of the given %% @doc Returns an flattened list containing the ASCII representation of the given
%% term. %% term.
-spec fprint(term(), pos_integer()) -> string().
fprint(T, Max) -> fprint(T, Max) ->
{L, _} = print(T, Max), {L, _} = print(T, Max),
lists:flatten(L). lists:flatten(L).
Expand All @@ -49,13 +50,15 @@ fprint(T, Max) ->
%% depth-limited instead of length limited, so you might run out %% depth-limited instead of length limited, so you might run out
%% memory printing it. Out of the frying pan and into the fire. %% memory printing it. Out of the frying pan and into the fire.
%% %%
-spec safe(term(), pos_integer()) -> {string(), pos_integer()} | {string()}.
safe(What, Len) -> safe(What, Len) ->
case catch print(What, Len) of case catch print(What, Len) of
{L, Used} when is_list(L) -> {L, Used}; {L, Used} when is_list(L) -> {L, Used};
_ -> {"unable to print" ++ io_lib:write(What, 99)} _ -> {"unable to print" ++ io_lib:write(What, 99)}
end. end.


%% @doc Returns {List, Length} %% @doc Returns {List, Length}
-spec print(term(), pos_integer()) -> {iolist(), pos_integer()}.
print(_, Max) when Max < 0 -> {"...", 3}; print(_, Max) when Max < 0 -> {"...", 3};
print(Tuple, Max) when is_tuple(Tuple) -> print(Tuple, Max) when is_tuple(Tuple) ->
{TC, Len} = tuple_contents(Tuple, Max-2), {TC, Len} = tuple_contents(Tuple, Max-2),
Expand Down Expand Up @@ -166,9 +169,11 @@ alist(L, Max) ->


%%-------------------- %%--------------------
%% The start of a test suite. So far, it only checks for not crashing. %% The start of a test suite. So far, it only checks for not crashing.
-spec test() -> ok.
test() -> test() ->
test(trunc_io, print). test(trunc_io, print).


-spec test(atom(), atom()) -> ok.
test(Mod, Func) -> test(Mod, Func) ->
Simple_items = [atom, 1234, 1234.0, {tuple}, [], [list], "string", self(), Simple_items = [atom, 1234, 1234.0, {tuple}, [], [list], "string", self(),
<<1,2,3>>, make_ref(), fun() -> ok end], <<1,2,3>>, make_ref(), fun() -> ok end],
Expand Down Expand Up @@ -196,19 +201,22 @@ test(Mod, Func) ->


lists:foreach(G, Tuples), lists:foreach(G, Tuples),
lists:foreach(G, Lists). lists:foreach(G, Lists).


-spec perf() -> ok.
perf() -> perf() ->
{New, _} = timer:tc(trunc_io, perf, [trunc_io, print, 1000]), {New, _} = timer:tc(trunc_io, perf, [trunc_io, print, 1000]),
{Old, _} = timer:tc(trunc_io, perf, [io_lib, write, 1000]), {Old, _} = timer:tc(trunc_io, perf, [io_lib, write, 1000]),
io:fwrite("New code took ~p us, old code ~p\n", [New, Old]). io:fwrite("New code took ~p us, old code ~p\n", [New, Old]).


-spec perf(atom(), atom(), integer()) -> done.
perf(M, F, Reps) when Reps > 0 -> perf(M, F, Reps) when Reps > 0 ->
test(M,F), test(M,F),
perf(M,F,Reps-1); perf(M,F,Reps-1);
perf(_,_,_) -> perf(_,_,_) ->
done. done.


%% Performance test. Needs a particularly large term I saved as a binary... %% Performance test. Needs a particularly large term I saved as a binary...
-spec perf1() -> {non_neg_integer(), non_neg_integer()}.
perf1() -> perf1() ->
{ok, Bin} = file:read_file("bin"), {ok, Bin} = file:read_file("bin"),
A = binary_to_term(Bin), A = binary_to_term(Bin),
Expand Down