aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2016-09-13 17:00:11 +0200
committerRickard Green <[email protected]>2016-09-13 17:00:51 +0200
commit809e70d0c8060f5d96584179b30950344ef51367 (patch)
treef74f21e0119a3096150a7d988cdd627bf61d96b9
parent71894a879d6254693791585246ce340dd7414b82 (diff)
downloadotp-809e70d0c8060f5d96584179b30950344ef51367.tar.gz
otp-809e70d0c8060f5d96584179b30950344ef51367.tar.bz2
otp-809e70d0c8060f5d96584179b30950344ef51367.zip
Fix crash due to heap fragments left after GC
Do not decode distribution messages as part of the GC operation. Distribution messages containing maps may generate heap fragments.
-rw-r--r--erts/emulator/beam/erl_gc.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index d0d74bbf44..9e0919cc9c 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -531,9 +531,19 @@ young_gen_usage(Process *p)
if (p->flags & F_ON_HEAP_MSGQ) {
ErtsMessage *mp;
- for (mp = p->msg.first; mp; mp = mp->next)
+ for (mp = p->msg.first; mp; mp = mp->next) {
+ /*
+ * We leave not yet decoded distribution messages
+ * as they are in the queue since it is not
+ * possible to determine a maximum size until
+ * actual decoding. However, we use their estimated
+ * size when calculating need, and by this making
+ * it more likely that they will fit on the heap
+ * when actually decoded.
+ */
if (mp->data.attached)
hsz += erts_msg_attached_data_size(mp);
+ }
}
aheap = p->abandoned_heap;
@@ -2247,37 +2257,22 @@ move_msgq_to_heap(Process *p)
if (mp->data.attached) {
ErlHeapFragment *bp;
- ErtsHeapFactory factory;
-
- erts_factory_proc_prealloc_init(&factory, p,
- erts_msg_attached_data_size(mp));
-
- if (is_non_value(ERL_MESSAGE_TERM(mp))) {
- if (mp->data.dist_ext) {
- ASSERT(mp->data.dist_ext->heap_size >= 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(mp))) {
- bp = erts_dist_ext_trailer(mp->data.dist_ext);
- ERL_MESSAGE_TOKEN(mp) = copy_struct(ERL_MESSAGE_TOKEN(mp),
- bp->used_size,
- &factory.hp,
- factory.off_heap);
- erts_cleanup_offheap(&bp->off_heap);
- }
- ERL_MESSAGE_TERM(mp) = erts_decode_dist_ext(&factory,
- mp->data.dist_ext);
- erts_free_dist_ext_copy(mp->data.dist_ext);
- mp->data.dist_ext = NULL;
- }
- }
- else {
+
+ /*
+ * We leave not yet decoded distribution messages
+ * as they are in the queue since it is not
+ * possible to determine a maximum size until
+ * actual decoding...
+ */
+ if (is_value(ERL_MESSAGE_TERM(mp))) {
bp = erts_message_to_heap_frag(mp);
if (bp->next)
- erts_move_multi_frags(&factory.hp, factory.off_heap, bp,
+ erts_move_multi_frags(&p->htop, &p->off_heap, bp,
mp->m, ERL_MESSAGE_REF_ARRAY_SZ, 0);
else
- copy_one_frag(&factory.hp, factory.off_heap, bp,
+ copy_one_frag(&p->htop, &p->off_heap, bp,
mp->m, ERL_MESSAGE_REF_ARRAY_SZ);
if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
@@ -2294,8 +2289,6 @@ move_msgq_to_heap(Process *p)
mp = new_mp;
}
}
-
- erts_factory_close(&factory);
}
mpp = &(*mpp)->next;