mirror of
https://github.com/correl/rebar.git
synced 2024-11-23 19:19:54 +00:00
update group leaders when restarting user process
ensure any processes with a reference to an old user process as their group leader are updated to use the new user process. this introduces a slight delay at startup as the system must wait for the new processes to be registered. there is a max wait period of three seconds (before the shell command gives up and throws a timeout error) fixes #314 ("rebar shell" somehow blocks using io:format in gen_server handle_call)
This commit is contained in:
parent
0d1ae7a468
commit
68089c6297
1 changed files with 26 additions and 4 deletions
|
@ -41,10 +41,20 @@
|
||||||
|
|
||||||
shell(_Config, _AppFile) ->
|
shell(_Config, _AppFile) ->
|
||||||
true = code:add_pathz(rebar_utils:ebin_dir()),
|
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
|
%% terminate the current user
|
||||||
ok = supervisor:terminate_child(kernel_sup, user),
|
ok = supervisor:terminate_child(kernel_sup, user),
|
||||||
%% start a new shell (this also starts a new user under the correct group)
|
%% 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
|
%% enable error_logger's tty output
|
||||||
ok = error_logger:swap_handler(tty),
|
ok = error_logger:swap_handler(tty),
|
||||||
%% disable the simple error_logger (which may have been added multiple
|
%% disable the simple error_logger (which may have been added multiple
|
||||||
|
@ -58,7 +68,8 @@ info(help, shell) ->
|
||||||
?CONSOLE(
|
?CONSOLE(
|
||||||
"Start a shell with project and deps preloaded similar to~n"
|
"Start a shell with project and deps preloaded similar to~n"
|
||||||
"'erl -pa ebin -pa deps/*/ebin'.~n",
|
"'erl -pa ebin -pa deps/*/ebin'.~n",
|
||||||
[]).
|
[]
|
||||||
|
).
|
||||||
|
|
||||||
remove_error_handler(0) ->
|
remove_error_handler(0) ->
|
||||||
?WARN("Unable to remove simple error_logger handler~n", []);
|
?WARN("Unable to remove simple error_logger handler~n", []);
|
||||||
|
@ -67,3 +78,14 @@ remove_error_handler(N) ->
|
||||||
{error, module_not_found} -> ok;
|
{error, module_not_found} -> ok;
|
||||||
{error_logger, _} -> remove_error_handler(N-1)
|
{error_logger, _} -> remove_error_handler(N-1)
|
||||||
end.
|
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.
|
Loading…
Reference in a new issue