diff --git a/src/rebar_shell.erl b/src/rebar_shell.erl index 348e540..0220a79 100644 --- a/src/rebar_shell.erl +++ b/src/rebar_shell.erl @@ -41,10 +41,20 @@ shell(_Config, _AppFile) -> true = code:add_pathz(rebar_utils:ebin_dir()), + %% scan all processes for any with references to the old user and save them to + %% update later + NeedsUpdate = [Pid || Pid <- erlang:processes(), + proplists:get_value(group_leader, erlang:process_info(Pid)) == whereis(user) + ], %% terminate the current user ok = supervisor:terminate_child(kernel_sup, user), %% start a new shell (this also starts a new user under the correct group) - user_drv:start(), + _ = user_drv:start(), + %% wait until user_drv and user have been registered (max 3 seconds) + ok = wait_until_user_started(3000), + %% set any process that had a reference to the old user's group leader to the + %% new user process + _ = [erlang:group_leader(whereis(user), Pid) || Pid <- NeedsUpdate], %% enable error_logger's tty output ok = error_logger:swap_handler(tty), %% disable the simple error_logger (which may have been added multiple @@ -56,9 +66,10 @@ shell(_Config, _AppFile) -> info(help, shell) -> ?CONSOLE( - "Start a shell with project and deps preloaded similar to~n" - "'erl -pa ebin -pa deps/*/ebin'.~n", - []). + "Start a shell with project and deps preloaded similar to~n" + "'erl -pa ebin -pa deps/*/ebin'.~n", + [] + ). remove_error_handler(0) -> ?WARN("Unable to remove simple error_logger handler~n", []); @@ -66,4 +77,15 @@ remove_error_handler(N) -> case gen_event:delete_handler(error_logger, error_logger, []) of {error, module_not_found} -> ok; {error_logger, _} -> remove_error_handler(N-1) + end. + +%% Timeout is a period to wait before giving up +wait_until_user_started(0) -> + ?ABORT("Timeout exceeded waiting for `user` to register itself~n", []), + erlang:error(timeout); +wait_until_user_started(Timeout) -> + case whereis(user) of + %% if user is not yet registered wait a tenth of a second and try again + undefined -> timer:sleep(100), wait_until_user_started(Timeout - 100); + _ -> ok end. \ No newline at end of file