summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/erl_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r--erts/emulator/beam/erl_process.c34
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: {