From 79efde2d8503e5055ef9e8afa5d8d63208710b1f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 16 Dec 2015 20:03:32 +0100 Subject: erts: Make copy_literals more fail safe * Same process must do enable-disable. * System process will force it and never get 'aborted' --- erts/emulator/beam/beam_bif_load.c | 28 +++++++++++++++++----------- erts/emulator/beam/global.h | 1 + erts/preloaded/ebin/erts_code_purger.beam | Bin 8996 -> 8832 bytes erts/preloaded/src/erts_code_purger.erl | 12 +++++------- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 39a5bff04c..892b2d16c2 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -1013,7 +1013,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) static void copy_literals_commit(void*); #endif -copy_literals_t erts_clrange = {NULL, 0}; +copy_literals_t erts_clrange = {NULL, 0, THE_NON_VALUE}; /* copy literals * @@ -1033,7 +1033,6 @@ copy_literals_t erts_clrange = {NULL, 0}; BIF_RETTYPE erts_internal_copy_literals_2(BIF_ALIST_2) { - Module* modp; ErtsCodeIndex code_ix; Eterm res = am_true; @@ -1048,21 +1047,28 @@ BIF_RETTYPE erts_internal_copy_literals_2(BIF_ALIST_2) code_ix = erts_active_code_ix(); - if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL || !modp->old.code_hdr) { - res = am_false; - goto done; - } - if (BIF_ARG_2 == am_true) { - if (erts_clrange.ptr != NULL) { + Module* modp = erts_get_module(BIF_ARG_1, code_ix); + if (!modp || !modp->old.code_hdr) { + res = am_false; + goto done; + } + if (erts_clrange.ptr != NULL + && !(BIF_P->static_flags & ERTS_STC_FLG_SYSTEM_PROC)) { res = am_aborted; goto done; - } - erts_clrange.ptr = (Eterm*) modp->old.code_hdr->literals_start; - erts_clrange.sz = (Eterm*) modp->old.code_hdr->literals_end - erts_clrange.ptr; + } + erts_clrange.ptr = modp->old.code_hdr->literals_start; + erts_clrange.sz = modp->old.code_hdr->literals_end - erts_clrange.ptr; + erts_clrange.pid = BIF_P->common.id; } else if (BIF_ARG_2 == am_false) { + if (erts_clrange.pid != BIF_P->common.id) { + res = am_false; + goto done; + } erts_clrange.ptr = NULL; erts_clrange.sz = 0; + erts_clrange.pid = THE_NON_VALUE; } #ifdef ERTS_SMP diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 0bf5988244..bbf684d49d 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -990,6 +990,7 @@ Eterm erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *red typedef struct { Eterm *ptr; Uint sz; + Eterm pid; } copy_literals_t; extern copy_literals_t erts_clrange; diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam index 74001fc799..c5aec6bb25 100644 Binary files a/erts/preloaded/ebin/erts_code_purger.beam and b/erts/preloaded/ebin/erts_code_purger.beam differ diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl index c7fe3ce22f..791ef72f13 100644 --- a/erts/preloaded/src/erts_code_purger.erl +++ b/erts/preloaded/src/erts_code_purger.erl @@ -63,11 +63,10 @@ purge(Mod) when is_atom(Mod) -> do_purge(Mod) -> - case erlang:check_old_code(Mod) of + case erts_internal:copy_literals(Mod, true) of false -> {false, false}; true -> - true = erts_internal:copy_literals(Mod, true), DidKill = check_proc_code(erlang:processes(), Mod, true), true = erts_internal:copy_literals(Mod, false), WasPurged = erts_internal:purge_module(Mod), @@ -89,17 +88,16 @@ soft_purge(Mod) -> do_soft_purge(Mod) -> - case erlang:check_old_code(Mod) of + case erts_internal:copy_literals(Mod, true) of false -> true; true -> - true = erts_internal:copy_literals(Mod, true), - case check_proc_code(erlang:processes(), Mod, false) of + DoPurge = check_proc_code(erlang:processes(), Mod, false), + true = erts_internal:copy_literals(Mod, false), + case DoPurge of false -> - true = erts_internal:copy_literals(Mod, false), false; true -> - true = erts_internal:copy_literals(Mod, false), erts_internal:purge_module(Mod), true end -- cgit v1.2.3