aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2015-12-16 20:03:32 +0100
committerSverker Eriksson <[email protected]>2016-01-13 19:59:54 +0100
commit79efde2d8503e5055ef9e8afa5d8d63208710b1f (patch)
tree77342e16ab227d8b9a175f4573305f244d17cceb
parentdc54c2a27c41930a18e0c7f2b97eda6cd4a0b1c1 (diff)
downloadotp-79efde2d8503e5055ef9e8afa5d8d63208710b1f.tar.gz
otp-79efde2d8503e5055ef9e8afa5d8d63208710b1f.tar.bz2
otp-79efde2d8503e5055ef9e8afa5d8d63208710b1f.zip
erts: Make copy_literals more fail safe
* Same process must do enable-disable. * System process will force it and never get 'aborted'
-rw-r--r--erts/emulator/beam/beam_bif_load.c28
-rw-r--r--erts/emulator/beam/global.h1
-rw-r--r--erts/preloaded/ebin/erts_code_purger.beambin8996 -> 8832 bytes
-rw-r--r--erts/preloaded/src/erts_code_purger.erl12
4 files changed, 23 insertions, 18 deletions
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
--- a/erts/preloaded/ebin/erts_code_purger.beam
+++ b/erts/preloaded/ebin/erts_code_purger.beam
Binary files 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