diff options
author | Björn Gustavsson <[email protected]> | 2016-05-03 06:51:25 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-05-04 10:21:30 +0200 |
commit | 7a1ff887383674e786a7c22aceefb0365ed91818 (patch) | |
tree | 4135603ed3372a6eb464f6ff20e05bfac5730130 /lib/kernel/test | |
parent | f8e4ac533d388b39d5980092e5dd7a9d4ffee60b (diff) | |
download | otp-7a1ff887383674e786a7c22aceefb0365ed91818.tar.gz otp-7a1ff887383674e786a7c22aceefb0365ed91818.tar.bz2 otp-7a1ff887383674e786a7c22aceefb0365ed91818.zip |
Correctly handle multiple load attempts when on_load is pending
If an on_load function had not yet returned, the code server
would only correctly handle calls to code:ensure_loaded/1. That
is, each process that called code:ensured_loaded/1 for the
module in question would be suspended until the on_load function
had returned.
The code server handled calls to code:load_binary/1, code:load_file/1,
and code:load_abs/1 in the same way as for code:ensure_loaded/1.
That means that if call to one those functions attempted to load
*different* code for the module, that code would not get loaded.
Note that code:finish_loading/1 (code:atomic_load/1) will still return
{error,pending_on_load} if there is a pending on_load function for one
of the modules that are about to be loaded. The reason is that
code:finish_loading/1 is meant to either succeed directly, or fail
quickly if there is any problem.
Diffstat (limited to 'lib/kernel/test')
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index e238eea2de..8da67c89f8 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -35,7 +35,7 @@ purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, on_load_update/1, - on_load_purge/1, on_load_self_call/1, + on_load_purge/1, on_load_self_call/1, on_load_pending/1, big_boot_embedded/1, native_early_modules/1, get_mode/1, normalized_paths/1]). @@ -65,7 +65,7 @@ all() -> purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, on_load_update, - on_load_purge, on_load_self_call, + on_load_purge, on_load_self_call, on_load_pending, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. groups() -> @@ -830,6 +830,12 @@ check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{code_server,run,2}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,handle_on_load,5}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,handle_pending_on_load,4}|_]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',2}, + [{code_server,finish_on_load_2,3}|_]) -> 0; %% This is cheating! /raimo %% %% check_funs(This = {M,_,_}, Path) -> @@ -1549,6 +1555,54 @@ on_load_do_load(Mod, Code) -> Any -> Any end. +on_load_pending(_Config) -> + Mod = ?FUNCTION_NAME, + Tree1 = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() ->\n", + " register('@Mod@', self()),\n", + " receive _ -> ok end.\n"]), + merl:print(Tree1), + {ok,Mod,Code1} = merl:compile(Tree1), + + Tree2 = ?Q(["-module('@Mod@').\n", + "-export([t/0]).\n", + "t() -> ok.\n"]), + merl:print(Tree2), + {ok,Mod,Code2} = merl:compile(Tree2), + + Self = self(), + {_,Ref1} = + spawn_monitor(fun() -> + Self ! started1, + {module,Mod} = code:load_binary(Mod, "", Code1) + end), + receive started1 -> ok end, + timer:sleep(10), + {_,Ref2} = + spawn_monitor(fun() -> + Self ! started2, + {module,Mod} = code:load_binary(Mod, "", Code2), + ok = Mod:t() + end), + receive started2 -> ok end, + receive + Unexpected -> + ct:fail({unexpected,Unexpected}) + after 100 -> + ok + end, + Mod ! go, + receive + {'DOWN',Ref1,process,_,normal} -> ok + end, + receive + {'DOWN',Ref2,process,_,normal} -> ok + end, + ok = Mod:t(), + ok. + + %% Test that the native code of early loaded modules is loaded. native_early_modules(Config) when is_list(Config) -> case erlang:system_info(hipe_architecture) of |