Skip to content

Commit 93667e1

Browse files
committed
erts: Fix call_memory tracing bug at delayed GC
The call to erts_adjust_memory_break(, orig_htop - p->high_water) must use the old value of p->high_water. Otherwise the reported call_memory value may get arbitrarily wrong, even negative number of words.
1 parent 6bf99d6 commit 93667e1

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

erts/emulator/beam/erl_gc.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,6 @@ delay_garbage_collection(Process *p, int need, int fcalls)
543543

544544
p->hend = hend;
545545

546-
/* Keep the high water mark pointing into the current heap to ensure
547-
* that the test for the safe range in the update_record_in_place (JIT)
548-
* stays honest. */
549-
p->high_water = p->heap;
550-
551546
if (p->abandoned_heap) {
552547
/*
553548
* Active heap already in a fragment; adjust it and
@@ -577,6 +572,11 @@ delay_garbage_collection(Process *p, int need, int fcalls)
577572
erts_adjust_memory_break(p, orig_htop - p->high_water);
578573
}
579574

575+
/* Keep the high water mark pointing into the current heap to ensure
576+
* that the test for the safe range in the update_record_in_place (JIT)
577+
* stays honest. */
578+
p->high_water = p->heap;
579+
580580
#ifdef CHECK_FOR_HOLES
581581
p->last_htop = p->htop;
582582
p->heap_hfrag = hfrag;

erts/emulator/test/trace_call_memory_SUITE.erl

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
spawn_memory/0, spawn_memory/1, spawn_memory_internal/1,
4242
spawn_memory_lambda/1,
4343
conflict_traces/0, conflict_traces/1,
44-
big_words/0, big_words/1
44+
big_words/0, big_words/1, delayed_gc/1
4545
]).
4646

4747
suite() ->
@@ -55,7 +55,7 @@ groups() ->
5555

5656
testcases() ->
5757
[basic, on_load, late_trace, skip, message, parallel_map, trace_all, spawn_memory,
58-
spawn_memory_lambda, conflict_traces, big_words].
58+
spawn_memory_lambda, conflict_traces, big_words, delayed_gc].
5959

6060
init_per_suite(Config) ->
6161
trace_sessions:init_per_suite(Config, ?MODULE).
@@ -116,6 +116,10 @@ end_per_testcase(conflict_traces, Config) ->
116116
end_per_testcase(big_words, Config) ->
117117
erlang_trace_pattern({?MODULE,alloc_tuples,2}, false, [call_memory]),
118118
erlang_trace(self(), false, [call]),
119+
trace_sessions:end_per_testcase(Config);
120+
end_per_testcase(delayed_gc, Config) ->
121+
erlang_trace_pattern({?MODULE, build_on_heap, 1}, false, [call_memory]),
122+
erlang_trace(self(), false, [call]),
119123
trace_sessions:end_per_testcase(Config).
120124

121125

@@ -451,3 +455,47 @@ alloc_tuples(0, _) ->
451455
alloc_tuples(N, TupleSz) ->
452456
erlang:make_tuple(TupleSz, []),
453457
alloc_tuples(N-1, TupleSz).
458+
459+
460+
%% OTP-19581
461+
%% Verify that reported memory is correct after getting disabled GC with "need".
462+
delayed_gc(Config) when is_list(Config) ->
463+
AIS = erts_debug:set_internal_state(available_internal_state, true),
464+
try
465+
Self = self(),
466+
Traced = {?MODULE, build_on_heap, 1},
467+
1 = erlang_trace_pattern(Traced, true, [call_memory]),
468+
1 = erlang_trace(Self, true, [call]),
469+
470+
{heap_size, HeapSize} = process_info(self(), heap_size),
471+
[begin
472+
%% Disable GC and fill up heap to trigger GC with need != 0
473+
%% which will provoke the abandoned heap scenario.
474+
true = erts_debug:set_internal_state(gc_state, false),
475+
Term = build_on_heap(Words),
476+
false = erts_debug:set_internal_state(gc_state, true),
477+
478+
?assertEqual(Words, erts_debug:flat_size(Term)),
479+
?assertEqual({call_memory, [{Self, 1, Words}]},
480+
erlang_trace_info(Traced, call_memory)),
481+
1 = erlang_trace_pattern(Traced, restart, [call_memory])
482+
end
483+
|| Words <- lists:seq(HeapSize, HeapSize*10, HeapSize)],
484+
485+
1 = erlang_trace(Self, false, [call]),
486+
1 = erlang_trace_pattern(Traced, false, [call_memory])
487+
after
488+
erts_debug:set_internal_state(available_internal_state, AIS)
489+
end,
490+
ok.
491+
492+
493+
build_on_heap(Words) ->
494+
build_on_heap(Words, []).
495+
496+
build_on_heap(0, Acc) ->
497+
Acc;
498+
build_on_heap(3, Acc) ->
499+
{3, Acc};
500+
build_on_heap(Words, Acc) when Words > 1 ->
501+
build_on_heap(Words-2, [Words | Acc]).

0 commit comments

Comments
 (0)