summaryrefslogtreecommitdiff
path: root/lib/kernel/src/group_history.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src/group_history.erl')
-rw-r--r--lib/kernel/src/group_history.erl108
1 files changed, 82 insertions, 26 deletions
diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl
index f50060cefa..b2cc05f5fd 100644
--- a/lib/kernel/src/group_history.erl
+++ b/lib/kernel/src/group_history.erl
@@ -20,6 +20,8 @@
-module(group_history).
-export([load/0, add/1]).
+-include_lib("kernel/include/logger.hrl").
+
%% Make a minimal size that should encompass set of lines and then make
%% a file rotation for N files of this size.
-define(DEFAULT_HISTORY_FILE, "erlang-shell-log").
@@ -66,7 +68,11 @@ load() ->
upgrade_version(?LOG_NAME, Version),
load();
{error, {badarg, size}} ->
- open_new_log(?LOG_NAME);
+ try open_new_log(?LOG_NAME)
+ catch exit:_ ->
+ %% Same reason as comment in catch below
+ []
+ end;
{error, Reason} ->
handle_open_error(Reason),
disable_history(),
@@ -79,33 +85,55 @@ load() ->
disabled ->
[];
Provider ->
- Provider:load()
+ try Provider:load() of
+ History when is_list(History) ->
+ History;
+ Error ->
+ show_custom_provider_faulty_load_return(Provider, Error),
+ disable_history(),
+ []
+ catch E:R:ST ->
+ show_custom_provider_crash(Provider, E, R, ST),
+ disable_history(),
+ []
+ end
end.
%% @doc adds a log line to the erlang history log, if configured to do so.
-spec add(iodata()) -> ok.
-add(Line) -> add(Line, history_status()).
-
-add(Line, enabled) ->
+add(Line) ->
case lists:member(Line, to_drop()) of
false ->
- case disk_log:log(?LOG_NAME, Line) of
- ok ->
- ok;
- {error, no_such_log} ->
- _ = open_log(), % a wild attempt we hope works!
- disk_log:log(?LOG_NAME, Line);
- {error, _Other} ->
- % just ignore, we're too late
- ok
- end;
+ add(Line, history_status());
true ->
ok
+ end.
+
+add(Line, enabled) ->
+ case disk_log:log(?LOG_NAME, Line) of
+ ok ->
+ ok;
+ {error, no_such_log} ->
+ _ = open_log(), % a wild attempt we hope works!
+ disk_log:log(?LOG_NAME, Line);
+ {error, _Other} ->
+ % just ignore, we're too late
+ ok
end;
add(_Line, disabled) ->
ok;
add(Line, Provider) ->
- lists:member(Line, to_drop()) orelse Provider:add(Line).
+ try Provider:add(Line) of
+ ok ->
+ ok;
+ Error ->
+ show_custom_provider_faulty_add_return(Provider, Error),
+ ok
+ catch E:R:ST ->
+ show_custom_provider_crash(Provider, E, R, ST),
+ disable_history(),
+ ok
+ end.
%%%%%%%%%%%%%%%
%%% PRIVATE %%%
@@ -215,6 +243,9 @@ read_full_log(Name) ->
{error, no_such_log} ->
show_unexpected_close_warning(),
[];
+ {error, Reason} ->
+ show_invalid_chunk_warning(Name, Reason),
+ [];
eof ->
[];
{Cont, Logs} ->
@@ -237,6 +268,9 @@ read_full_log(Name, Cont) ->
{error, no_such_log} ->
show_unexpected_close_warning(),
[];
+ {error, Reason} ->
+ show_invalid_chunk_warning(Name, Reason),
+ [];
eof ->
[];
{NextCont, Logs} ->
@@ -261,13 +295,11 @@ handle_open_error({invalid_header, Term}) ->
show('$#erlang-history-invalid-header',
"Shell history expects to be able to use the log files "
"which currently have unknown headers (~p) and may belong to "
- "another mechanism. History logging will be "
- "disabled.~n",
+ "another mechanism.~n",
[Term]);
handle_open_error({file_error, FileName, Reason}) ->
show('$#erlang-history-file-error',
- "Error handling File ~ts. Reason: ~p~n"
- "History logging will be disabled.~n",
+ "Error handling file ~ts. Reason: ~p~n",
[FileName, Reason]);
handle_open_error(Err) ->
show_unexpected_warning({disk_log, open, 1}, Err).
@@ -310,14 +342,14 @@ resize_log(Name, _OldSize, NewSize) ->
case disk_log:change_size(Name, NewSize) of
ok ->
show('$#erlang-history-resize-result',
- "ok~n", []);
+ "resized the log history file~n", []);
{error, {new_size_too_small, _, _}} -> % cannot happen
show('$#erlang-history-resize-result',
- "failed (new size is too small)~n", []),
+ "failed to resize the log history file (new size is too small)~n", []),
disable_history();
{error, Reason} ->
show('$#erlang-history-resize-result',
- "failed (~p)~n", [Reason]),
+ "failed to resize the log history file (~p)~n", [Reason]),
disable_history()
end,
_ = disk_log:close(?LOG_NAME),
@@ -360,12 +392,17 @@ show_rename_warning() ->
"name will keep being used for this session.~n",
[]).
+show_invalid_chunk_warning(Name, Reason) ->
+ show('$#erlang-history-invalid-chunk-warn',
+ "Invalid chunk in the file ~ts.~n"
+ "Some entries may have been lost.~nReason ~p.",
+ [proplists:get_value(file,disk_log:info(Name)), Reason]).
+
show_invalid_file_warning(FileName) ->
show('$#erlang-history-invalid-file',
"Shell history expects to be able to use the file ~ts "
"which currently exists and is not a file usable for "
- "history logging purposes. History logging will be "
- "disabled.~n", [FileName]).
+ "history logging purposes.~n", [FileName]).
show_unexpected_warning({M,F,A}, Term) ->
show('$#erlang-history-unexpected-return',
@@ -383,10 +420,29 @@ show_size_warning(_Current, _New) ->
"The configured log history file size is different from "
"the size of the log file on disk.~n", []).
+show_custom_provider_crash(Provider, Class, Reason, StackTrace) ->
+ show('$#erlang-history-custom-crash',
+ "The configured custom shell_history provider '~p' crashed. ~n"
+ "Did you mean to write 'enabled'?~n"
+ "~ts~n",
+ [Provider, erl_error:format_exception(Class, Reason, StackTrace)]).
+
+show_custom_provider_faulty_load_return(Provider, Return) ->
+ show('$#erlang-history-custom-return',
+ "The configured custom shell_history provider ~p:load/0 did not return a list.~n"
+ "It returned ~p.~n",
+ [Provider, Return]).
+
+show_custom_provider_faulty_add_return(Provider, Return) ->
+ show('$#erlang-history-custom-return',
+ "The configured custom shell_history provider ~p:add/1 did not return ok.~n"
+ "It returned ~p.~n",
+ [Provider, Return]).
+
show(Key, Format, Args) ->
case get(Key) of
undefined ->
- io:format(standard_error, Format, Args),
+ ?LOG_ERROR(Format, Args),
put(Key, true),
ok;
true ->