From 6b912d7fdd5fca46dee840b0bfa6a92915c0a093 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 3 Dec 2015 14:39:31 +0100 Subject: erts: Fix bug in heap_factory_undo for FACTORY_HEAP_FRAGS mode Make sure a heap fragment is not deallocated before all off_heap terms have been cleared. The fix assumes/asserts that the off_heap-lists of all additional heap fragments are empty. I think this bug has been harmless as hashmap nodes, which is only ones (?) that can cause a factory to produce more heap, are not linked in off_heap-list. --- erts/emulator/beam/erl_message.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'erts/emulator/beam/erl_message.c') diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index ef52823287..2a703fb102 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -1372,13 +1372,16 @@ void erts_factory_undo(ErtsHeapFactory* factory) break; case FACTORY_HEAP_FRAGS: + erts_cleanup_offheap(factory->off_heap); + factory->off_heap->first = NULL; + bp = factory->heap_frags; do { ErlHeapFragment* next_bp = bp->next; - erts_cleanup_offheap(&bp->off_heap); + ASSERT(bp->off_heap.first == NULL); ERTS_HEAP_FREE(factory->alloc_type, (void *) bp, - ERTS_HEAP_FRAG_SIZE(bp->size)); + ERTS_HEAP_FRAG_SIZE(bp->alloc_size)); bp = next_bp; }while (bp != NULL); break; -- cgit v1.2.3 From ce8279d6a48d41f9de577825844f499bb3084b96 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 3 Dec 2015 15:34:14 +0100 Subject: erts: Fix bug for remote control message containing fat maps that could cause the static factory to overflow Fix: Introduce a new factory mode FACTORY_TMP --- erts/emulator/beam/erl_message.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'erts/emulator/beam/erl_message.c') diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 2a703fb102..fa6b2fc613 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -1174,6 +1174,9 @@ void erts_factory_message_init(ErtsHeapFactory* factory, ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end); } +/* One static sized heap that must suffice. + No extra heap fragments will be allocated. +*/ void erts_factory_static_init(ErtsHeapFactory* factory, Eterm* hp, Uint size, @@ -1188,6 +1191,23 @@ void erts_factory_static_init(ErtsHeapFactory* factory, factory->off_heap_saved.overhead = factory->off_heap->overhead; } +/* A temporary heap with default buffer allocated/freed by client. + * factory_close is same as factory_undo + */ +void erts_factory_tmp_init(ErtsHeapFactory* factory, Eterm* hp, Uint size, + Uint32 atype) +{ + factory->mode = FACTORY_TMP; + factory->hp_start = hp; + factory->hp = hp; + factory->hp_end = hp + size; + factory->heap_frags = NULL; + factory->off_heap_saved.first = NULL; + factory->off_heap_saved.overhead = 0; + factory->off_heap = &factory->off_heap_saved; + factory->alloc_type = atype; +} + /* When we know the term is an immediate and need no heap. */ void erts_factory_dummy_init(ErtsHeapFactory* factory) @@ -1231,6 +1251,7 @@ static void reserve_heap(ErtsHeapFactory* factory, Uint need, Uint xtra) return; case FACTORY_HEAP_FRAGS: + case FACTORY_TMP: bp = factory->heap_frags; if (bp) { @@ -1280,6 +1301,9 @@ void erts_factory_close(ErtsHeapFactory* factory) bp->used_size = factory->hp - bp->mem; } break; + case FACTORY_TMP: + erts_factory_undo(factory); + break; case FACTORY_STATIC: break; case FACTORY_CLOSED: break; default: @@ -1371,19 +1395,20 @@ void erts_factory_undo(ErtsHeapFactory* factory) } break; + case FACTORY_TMP: case FACTORY_HEAP_FRAGS: erts_cleanup_offheap(factory->off_heap); factory->off_heap->first = NULL; bp = factory->heap_frags; - do { + while (bp != NULL) { ErlHeapFragment* next_bp = bp->next; ASSERT(bp->off_heap.first == NULL); ERTS_HEAP_FREE(factory->alloc_type, (void *) bp, ERTS_HEAP_FRAG_SIZE(bp->alloc_size)); bp = next_bp; - }while (bp != NULL); + } break; case FACTORY_CLOSED: break; -- cgit v1.2.3