diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2019-01-31 09:22:23 -0500 |
---|---|---|
committer | Fred Hebert <mononcqc@ferd.ca> | 2019-01-31 09:35:52 -0500 |
commit | 1b6e3ac9c0e3b77215b119427b9a4d530cb08e1d (patch) | |
tree | efb151a25307c3f2c13b0cd4034d5b9b2ceb003f /src | |
parent | 036e30ba2bcb7643c5a1603ff03232769b65c7a4 (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.
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_prv_shell.erl | 24 |
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), |