diff options
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index b9fed009aa..db13f87c76 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -12932,6 +12932,7 @@ enum continue_exit_phase { ERTS_CONTINUE_EXIT_MONITORS, ERTS_CONTINUE_EXIT_LT_MONITORS, ERTS_CONTINUE_EXIT_HANDLE_PROC_SIG, + ERTS_CONTINUE_EXIT_DIST_SEND, ERTS_CONTINUE_EXIT_DIST_LINKS, ERTS_CONTINUE_EXIT_DIST_MONITORS, ERTS_CONTINUE_EXIT_DONE, @@ -12949,6 +12950,10 @@ struct continue_exit_state { Uint32 block_rla_ref; }; +#ifdef DEBUG +extern Export dsend_continue_trap_export; +#endif + void erts_continue_exit_process(Process *p) { @@ -13186,6 +13191,20 @@ restart: trap_state->pectxt.dist_state = NIL; trap_state->pectxt.yield = 0; + p->rcount = 0; + + if (p->flags & F_FRAGMENTED_SEND) { + /* The process was re-scheduled while doing a fragmented + distributed send (possibly because it was suspended). + We need to finish doing that send as otherwise incomplete + fragmented messages will be sent to other nodes potentially + causing memory leaks. + */ + ASSERT(p->current == &dsend_continue_trap_export.info.mfa); + /* arg_reg[0] is the argument used in dsend_continue_trap_export */ + trap_state->pectxt.dist_state = p->arg_reg[0]; + } + erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); erts_proc_sig_fetch(p); @@ -13244,11 +13263,12 @@ restart: reds -= r; - trap_state->phase = ERTS_CONTINUE_EXIT_DIST_LINKS; + trap_state->phase = ERTS_CONTINUE_EXIT_DIST_SEND; } - case ERTS_CONTINUE_EXIT_DIST_LINKS: { + case ERTS_CONTINUE_EXIT_DIST_SEND: { - continue_dist_send: + continue_dist_send: + ASSERT(p->rcount == 0); if (is_not_nil(trap_state->pectxt.dist_state)) { Binary* bin = erts_magic_ref2bin(trap_state->pectxt.dist_state); ErtsDSigSendContext* ctx = (ErtsDSigSendContext*) ERTS_MAGIC_BIN_DATA(bin); @@ -13281,6 +13301,13 @@ restart: goto restart; } + trap_state->phase = ERTS_CONTINUE_EXIT_DIST_LINKS; + } + case ERTS_CONTINUE_EXIT_DIST_LINKS: { + + if (is_not_nil(trap_state->pectxt.dist_state)) + goto continue_dist_send; + reds = erts_link_tree_foreach_delete_yielding( &trap_state->pectxt.dist_links, erts_proc_exit_handle_dist_link, @@ -13289,6 +13316,7 @@ restart: reds); if (reds <= 0 || trap_state->pectxt.yield) goto yield; + trap_state->phase = ERTS_CONTINUE_EXIT_DIST_MONITORS; } case ERTS_CONTINUE_EXIT_DIST_MONITORS: { |