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
4747suite () ->
@@ -55,7 +55,7 @@ groups() ->
5555
5656testcases () ->
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
6060init_per_suite (Config ) ->
6161 trace_sessions :init_per_suite (Config , ? MODULE ).
@@ -116,6 +116,10 @@ end_per_testcase(conflict_traces, Config) ->
116116end_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, _) ->
451455alloc_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