From fa44f865c3fc6253cf4691cf94839c303a3ee40f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 15 Dec 2015 20:32:39 +0100 Subject: erts: Make erlang:purge_module/1 safe Problem: erlang:purge_module/1 is not safe in the sense that very bad things may happen if the code to be purged is still referred to by live processes. Introduce erts_internal:purge_module which is the same as the old erlang:purge_module BIF (except it returns false if no such old module). Implement erlang:purge_module in Erlang and let it invoke erts_code_purger for safe purging where all clogging processes first are killed. --- erts/preloaded/src/erlang.erl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'erts/preloaded/src/erlang.erl') diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index d9dc9a1976..ab54d716cc 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1471,8 +1471,16 @@ processes() -> %% purge_module/1 -spec purge_module(Module) -> true when Module :: atom(). -purge_module(_Module) -> - erlang:nif_error(undefined). +purge_module(Module) when erlang:is_atom(Module) -> + case erts_code_purger:purge(Module) of + {false, _} -> + erlang:error(badarg, [Module]); + {true, _} -> + true + end; +purge_module(Arg) -> + erlang:error(badarg, [Arg]). + %% put/2 -spec put(Key, Val) -> term() when -- cgit v1.2.3 From dc54c2a27c41930a18e0c7f2b97eda6cd4a0b1c1 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 16 Dec 2015 19:11:48 +0100 Subject: erts: Move copy_literals/2 from erlang to erts_internal as it's not a public interface. --- erts/preloaded/src/erlang.erl | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'erts/preloaded/src/erlang.erl') diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index ab54d716cc..0a41951900 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -91,7 +91,7 @@ -export([bit_size/1, bitsize/1, bitstring_to_list/1]). -export([bump_reductions/1, byte_size/1, call_on_load_function/1]). -export([cancel_timer/1, cancel_timer/2, check_old_code/1, check_process_code/2, - check_process_code/3, copy_literals/2, crc32/1]). + check_process_code/3, crc32/1]). -export([crc32/2, crc32_combine/3, date/0, decode_packet/3]). -export([delete_element/2]). -export([delete_module/1, demonitor/1, demonitor/2, display/1]). @@ -520,13 +520,6 @@ get_cpc_opts([{allow_gc, AllowGC} | Options], Async, _OldAllowGC) -> get_cpc_opts([], Async, AllowGC) -> {Async, AllowGC}. -%% copy_literals/2 --spec erlang:copy_literals(Module,Bool) -> 'true' | 'false' | 'aborted' when - Module :: module(), - Bool :: boolean(). -copy_literals(_Mod, _Bool) -> - erlang:nif_error(undefined). - %% crc32/1 -spec erlang:crc32(Data) -> non_neg_integer() when Data :: iodata(). -- cgit v1.2.3 From a4920dc4045f394f6f4ab1cc89d54d55722a66d6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 12 Jan 2016 17:02:06 +0100 Subject: erts: Refactor check_process_code/3 Move impl from erlang to erts_internal. Cut and paste. --- erts/preloaded/src/erlang.erl | 44 ++----------------------------------------- 1 file changed, 2 insertions(+), 42 deletions(-) (limited to 'erts/preloaded/src/erlang.erl') diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 0a41951900..40d5aedd24 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -460,7 +460,7 @@ check_old_code(_Module) -> CheckResult :: boolean(). check_process_code(Pid, Module) -> try - erlang:check_process_code(Pid, Module, [{allow_gc, true}]) + erts_internal:check_process_code(Pid, Module, [{allow_gc, true}]) catch error:Error -> erlang:error(Error, [Pid, Module]) end. @@ -475,51 +475,11 @@ check_process_code(Pid, Module) -> CheckResult :: boolean() | aborted. check_process_code(Pid, Module, OptionList) -> try - {Async, AllowGC} = get_cpc_opts(OptionList, sync, true), - case Async of - {async, ReqId} -> - {priority, Prio} = erlang:process_info(erlang:self(), - priority), - erts_internal:request_system_task(Pid, - Prio, - {check_process_code, - ReqId, - Module, - AllowGC}), - async; - sync -> - case Pid == erlang:self() of - true -> - erts_internal:check_process_code(Module, - [{allow_gc, AllowGC}]); - false -> - {priority, Prio} = erlang:process_info(erlang:self(), - priority), - ReqId = erlang:make_ref(), - erts_internal:request_system_task(Pid, - Prio, - {check_process_code, - ReqId, - Module, - AllowGC}), - receive - {check_process_code, ReqId, CheckResult} -> - CheckResult - end - end - end + erts_internal:check_process_code(Pid, Module, OptionList) catch error:Error -> erlang:error(Error, [Pid, Module, OptionList]) end. -% gets async and allow_gc opts and verify valid option list -get_cpc_opts([{async, _ReqId} = AsyncTuple | Options], _OldAsync, AllowGC) -> - get_cpc_opts(Options, AsyncTuple, AllowGC); -get_cpc_opts([{allow_gc, AllowGC} | Options], Async, _OldAllowGC) -> - get_cpc_opts(Options, Async, AllowGC); -get_cpc_opts([], Async, AllowGC) -> - {Async, AllowGC}. - %% crc32/1 -spec erlang:crc32(Data) -> non_neg_integer() when Data :: iodata(). -- cgit v1.2.3