summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2019-01-31 09:22:23 -0500
committerFred Hebert <mononcqc@ferd.ca>2019-01-31 09:35:52 -0500
commit1b6e3ac9c0e3b77215b119427b9a4d530cb08e1d (patch)
treeefb151a25307c3f2c13b0cd4034d5b9b2ceb003f
parent036e30ba2bcb7643c5a1603ff03232769b65c7a4 (diff)
Unhang logger when swapping the TTY in shell
Starting with OTP-21.2.3, some output appears to be sent to the shell while we're taking down the TTY, which ends up stalling the whole log flow for the default handler. I don't have proof but suspect this is due to the system logging going directly from the ERTS runtime to the logger, which may be trigger when we kill the TTY driver. This patch makes it so whenever we detect that logger is active, we save the default config, disable the default logger, and only then we can kill the TTY driver. Once the driver is started and all the group leaders have been rewritten, the default logger is re-added. This all takes place _before_ the logger configuration is updated as part of booting apps, and the change should be fully backwards compatible.
-rw-r--r--src/rebar_prv_shell.erl24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 760f0d8..4ba3c39 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -128,6 +128,7 @@ info() ->
"Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n".
setup_shell(ShellArgs) ->
+ LoggerState = maybe_remove_logger(),
OldUser = kill_old_user(),
%% Test for support here
NewUser = try erlang:open_port({spawn,"tty_sl -c -e"}, []) of
@@ -138,7 +139,28 @@ setup_shell(ShellArgs) ->
error:_ ->
setup_old_shell()
end,
- rewrite_leaders(OldUser, NewUser).
+ rewrite_leaders(OldUser, NewUser),
+ maybe_reset_logger(LoggerState).
+
+%% @private starting with OTP-21.2.3, there's an oddity where the logger
+%% likely tries to handle system logs while we take down the TTY, which
+%% ends up hanging the default logger. This function (along with
+%% `maybe_reset_logger/1') removes and re-adds the default logger before and
+%% after the TTY subsystem is taken offline, which prevents such hanging.
+maybe_remove_logger() ->
+ case erlang:function_exported(logger, module_info, 0) of
+ false ->
+ ignore;
+ true ->
+ {ok, Cfg} = logger:get_handler_config(default),
+ logger:remove_handler(default),
+ {restart, Cfg}
+ end.
+
+maybe_reset_logger(ignore) ->
+ ok;
+maybe_reset_logger({restart, #{module := Mod, config := Cfg}}) ->
+ logger:add_handler(default, Mod, Cfg).
kill_old_user() ->
OldUser = whereis(user),