diff options
author | Björn Gustavsson <[email protected]> | 2016-09-15 11:40:39 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-09-15 11:40:39 +0200 |
commit | 687eae1e86817403249f03f534a256a28c5d5251 (patch) | |
tree | 75369a6be94deb0e0c0ad2287102dbb16c34b026 /erts/preloaded/src | |
parent | 060949fb1ee7d1af366372b43dde5add421a5f73 (diff) | |
parent | fde238fb52133a6c7a2a3f2a2e16f1c1bef62394 (diff) | |
download | otp-687eae1e86817403249f03f534a256a28c5d5251.tar.gz otp-687eae1e86817403249f03f534a256a28c5d5251.tar.bz2 otp-687eae1e86817403249f03f534a256a28c5d5251.zip |
Merge branch 'maint'
* maint:
erts: Add nif_SUITE:t_on_load
erts: Improve nif_SUITE:upgrade test
Don't leak old code when loading a modules with an on_load function
Conflicts:
erts/preloaded/ebin/erts_code_purger.beam
erts/preloaded/ebin/erts_internal.beam
erts/preloaded/src/erts_code_purger.erl
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r-- | erts/preloaded/src/erts_code_purger.erl | 39 | ||||
-rw-r--r-- | erts/preloaded/src/erts_internal.erl | 2 |
2 files changed, 39 insertions, 2 deletions
diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl index a48aebe4e7..fd214228c7 100644 --- a/erts/preloaded/src/erts_code_purger.erl +++ b/erts/preloaded/src/erts_code_purger.erl @@ -22,7 +22,8 @@ %% Purpose : Implement system process erts_code_purger %% to handle code module purging. --export([start/0, purge/1, soft_purge/1, pending_purge_lambda/3]). +-export([start/0, purge/1, soft_purge/1, pending_purge_lambda/3, + finish_after_on_load/2]). -spec start() -> term(). start() -> @@ -41,6 +42,11 @@ handle_request({soft_purge, Mod, From, Ref}, Reqs) when is_atom(Mod), is_pid(Fro {Res, NewReqs} = do_soft_purge(Mod, Reqs), From ! {reply, soft_purge, Res, Ref}, check_requests(NewReqs); +handle_request({finish_after_on_load, {Mod,Keep}, From, Ref}, Reqs) + when is_atom(Mod), is_boolean(Keep), is_pid(From) -> + NewReqs = do_finish_after_on_load(Mod, Keep, Reqs), + From ! {reply, finish_after_on_load, ok, Ref}, + check_requests(NewReqs); handle_request({test_purge, Mod, From, Type, Ref}, Reqs) when is_atom(Mod), is_pid(From) -> NewReqs = do_test_purge(Mod, From, Type, Ref, Reqs), check_requests(NewReqs); @@ -132,6 +138,37 @@ do_soft_purge(Mod, Reqs) -> {erts_internal:purge_module(Mod, PurgeOp), NewReqs} end. +%% finish_after_on_load(Module, Keep) +%% Finish after running on_load function. If Keep is false, +%% purge the code for the on_load function. + +finish_after_on_load(Mod, Keep) -> + Ref = make_ref(), + erts_code_purger ! {finish_after_on_load, {Mod,Keep}, self(), Ref}, + receive + {reply, finish_after_on_load, Result, Ref} -> + Result + end. + +do_finish_after_on_load(Mod, Keep, Reqs) -> + erlang:finish_after_on_load(Mod, Keep), + case Keep of + true -> + Reqs; + false -> + case erts_internal:purge_module(Mod, prepare_on_load) of + false -> + Reqs; + true -> + {_DidKill, NewReqs} = + check_proc_code(erlang:processes(), + Mod, true, Reqs), + true = erts_internal:purge_module(Mod, complete), + NewReqs + end + end. + + %% %% check_proc_code(Pids, Mod, Hard, Preqs) - Send asynchronous %% requests to all processes to perform a check_process_code diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl index 438fa477e6..fecdfc348c 100644 --- a/erts/preloaded/src/erts_internal.erl +++ b/erts/preloaded/src/erts_internal.erl @@ -302,7 +302,7 @@ release_literal_area_switch() -> -spec purge_module(Module, Op) -> boolean() when Module :: module(), - Op :: 'prepare' | 'abort' | 'complete'. + Op :: 'prepare' | 'prepare_on_load' | 'abort' | 'complete'. purge_module(_Module, _Op) -> erlang:nif_error(undefined). |