diff options
author | Björn Gustavsson <[email protected]> | 2010-10-19 13:43:13 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2010-10-20 12:02:08 +0200 |
commit | 7f82eddfaa3b89f734b4d58f1de92db86e5880cf (patch) | |
tree | d006dcb6f6c022ee875b32e75415c3793eb9cb7a /erts/preloaded/src/init.erl | |
parent | c09fa792fad151f43cd3fa3d998b666a91badc5e (diff) | |
download | otp-7f82eddfaa3b89f734b4d58f1de92db86e5880cf.tar.gz otp-7f82eddfaa3b89f734b4d58f1de92db86e5880cf.tar.bz2 otp-7f82eddfaa3b89f734b4d58f1de92db86e5880cf.zip |
Fix hang in on_load handlers in embedded mode
In embedded mode, all on_load handlers will be called after
loading all modules but before starting any servers. Therefore,
if an on_load handler calls any function in the code module that
calls the code server (such as code:priv_dir/1), there will be a
deadlock because the code server has not yet been started.
Fix this problem by invoking the on_load handlers after
having started most servers in the kernel application.
Diffstat (limited to 'erts/preloaded/src/init.erl')
-rw-r--r-- | erts/preloaded/src/init.erl | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 3b98b9cddc..255f33c299 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -51,6 +51,9 @@ get_status/0,boot/1,get_arguments/0,get_plain_arguments/0, get_argument/1,script_id/0]). +%% for the on_load functionality; not for general use +-export([run_on_load_handlers/0]). + %% internal exports -export([fetch_loaded/0,ensure_loaded/1,make_permanent/2, notify_when_started/1,wait_until_started/0, @@ -308,24 +311,6 @@ boot_loop(BootPid, State) -> {stop,Reason} -> stop(Reason,State); {From,fetch_loaded} -> %% Fetch and reset initially loaded modules. - case whereis(?ON_LOAD_HANDLER) of - undefined -> - %% There is no on_load handler process, - %% probably because init:restart/0 has been - %% called and it is not the first time we - %% pass through here. - ok; - Pid when is_pid(Pid) -> - Pid ! run_on_load, - receive - {'EXIT',Pid,on_load_done} -> - ok; - {'EXIT',Pid,Res} -> - %% Failure to run an on_load handler. - %% This is fatal during start-up. - exit(Res) - end - end, From ! {init,State#state.loaded}, garb_boot_loop(BootPid,State#state{loaded = []}); {From,{ensure_loaded,Module}} -> @@ -1335,9 +1320,27 @@ archive_extension() -> %%% Support for handling of on_load functions. %%% +run_on_load_handlers() -> + Ref = monitor(process, ?ON_LOAD_HANDLER), + catch ?ON_LOAD_HANDLER ! run_on_load, + receive + {'DOWN',Ref,process,_,noproc} -> + %% There is no on_load handler process, + %% probably because init:restart/0 has been + %% called and it is not the first time we + %% pass through here. + ok; + {'DOWN',Ref,process,_,on_load_done} -> + ok; + {'DOWN',Ref,process,_,Res} -> + %% Failure to run an on_load handler. + %% This is fatal during start-up. + exit(Res) + end. + start_on_load_handler_process() -> register(?ON_LOAD_HANDLER, - spawn_link(fun on_load_handler_init/0)). + spawn(fun on_load_handler_init/0)). on_load_handler_init() -> on_load_loop([]). |