diff options
author | Erlang/OTP <otp@erlang.org> | 2020-04-06 12:45:13 +0200 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2020-04-06 12:45:13 +0200 |
commit | 3bdb81e2d8f609b24fb06f14c1cbdf9ba56c2ffa (patch) | |
tree | 4f8a470664d10ec9f4c5fd1e2153e552f350ec2f /erts/emulator | |
parent | 7162fa04faca0e0aa8ad78bf0e00f77820643965 (diff) | |
parent | 8a71d0f980d734fdb09f9ac34a90fbffb4bd601e (diff) | |
download | erlang-3bdb81e2d8f609b24fb06f14c1cbdf9ba56c2ffa.tar.gz |
Merge branch 'john/erts/fix-cla-disable-gc/OTP-16555/ERL-1088' into maint-22
* john/erts/fix-cla-disable-gc/OTP-16555/ERL-1088:
erts: Delay copying literal area when GC is disabled
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 11 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 34 | ||||
-rw-r--r-- | erts/emulator/test/code_SUITE.erl | 42 |
3 files changed, 82 insertions, 5 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index a168c52006..a965f157ba 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -955,6 +955,14 @@ erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed if (!la) goto return_ok; + /* The heap may be in an inconsistent state when the GC is disabled, for + * example when we're in the middle of building a record in + * binary_to_term/1, so we have to delay scanning until the GC is enabled + * again. */ + if (c_p->flags & F_DISABLE_GC) { + return THE_NON_VALUE; + } + oh = la->off_heap; literals = (char *) &la->start[0]; lit_bsize = (char *) la->end - literals; @@ -1075,9 +1083,6 @@ literal_gc: if (!gc_allowed) return am_need_gc; - if (c_p->flags & F_DISABLE_GC) - return THE_NON_VALUE; - *redsp += erts_garbage_collect_literals(c_p, (Eterm *) literals, lit_bsize, oh, fcalls); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 9af5f3ea38..aee097840f 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4543,6 +4543,40 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) erts_set_gc_state(BIF_P, enable); BIF_RET(res); } + else if (ERTS_IS_ATOM_STR("inconsistent_heap", BIF_ARG_1)) { + /* Used by code_SUITE (emulator) */ + if (am_start == BIF_ARG_2) { + Eterm broken_term; + Eterm *hp; + + ERTS_ASSERT(!(BIF_P->flags & F_DISABLE_GC)); + erts_set_gc_state(BIF_P, 0); + + hp = HAlloc(BIF_P, 2); + hp[0] = make_arityval(1234); + hp[1] = THE_NON_VALUE; + + broken_term = make_tuple(hp); + + BIF_RET(broken_term); + } else { + Eterm broken_term; + Eterm *hp; + + broken_term = BIF_ARG_2; + + hp = tuple_val(broken_term); + ERTS_ASSERT(hp[0] == make_arityval(1234)); + ERTS_ASSERT(hp[1] == THE_NON_VALUE); + hp[0] = make_arityval(1); + hp[1] = am_ok; + + ERTS_ASSERT(BIF_P->flags & F_DISABLE_GC); + erts_set_gc_state(BIF_P, 1); + + BIF_RET(am_ok); + } + } else if (ERTS_IS_ATOM_STR("colliding_names", BIF_ARG_1)) { /* Used by ets_SUITE (stdlib) */ if (is_tuple(BIF_ARG_2)) { diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index bb4880b150..5fbb5d5a9c 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -348,8 +348,25 @@ constant_pools(Config) when is_list(Config) -> receive {'EXIT',NoOldHeap,{A,B,C,D}} -> ok; - Other -> - ct:fail({unexpected,Other}) + Other_NoOldHeap -> + ct:fail({unexpected,Other_NoOldHeap}) + end, + {module,literals} = erlang:load_module(literals, Code), + + %% Have a process with an inconsistent heap (legal while GC is disabled) + %% that references the literals in the 'literals' module. + InconsistentHeap = spawn_link(fun() -> inconsistent_heap(Self) end), + receive go -> ok end, + true = erlang:delete_module(literals), + false = erlang:check_process_code(InconsistentHeap, literals), + erlang:check_process_code(self(), literals), + true = erlang:purge_module(literals), + InconsistentHeap ! done, + receive + {'EXIT',InconsistentHeap,{A,B,C}} -> + ok; + Other_InconsistentHeap -> + ct:fail({unexpected,Other_InconsistentHeap}) end, {module,literals} = erlang:load_module(literals, Code), @@ -424,6 +441,27 @@ old_heap(Parent) -> exit(Res) end. +inconsistent_heap(Parent) -> + A = literals:a(), + B = literals:b(), + C = literals:huge_bignum(), + Res = {A,B,C}, + Parent ! go, + + %% Disable the GC and return a tuple whose arity and contents are broken + BrokenTerm = erts_debug:set_internal_state(inconsistent_heap, start), + receive + after 5000 -> + %% Fix the tuple and enable the GC again + ok = erts_debug:set_internal_state(inconsistent_heap, BrokenTerm), + erlang:garbage_collect() + end, + + receive + done -> + exit(Res) + end. + hibernated(Parent) -> A = literals:a(), B = literals:b(), |