File 1154-erts-Fix-race-receiving-fragmented-msg-on-terminatin.patch of Package erlang
From 802cbebc9664977e7e2ec6b58d8dc9a179be71b1 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Tue, 20 Dec 2022 16:21:11 +0100
Subject: [PATCH] erts: Fix race receiving fragmented msg on terminating
connection
and spawn reply back to exiting parent on terminating connection.
---
erts/emulator/beam/dist.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index c79c0834f6..d13e44f3ee 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1953,10 +1953,14 @@ int erts_net_message(Port *prt,
seq->ctl_len = ctl_len;
seq->seq_id = ede.data->seq_id;
seq->cnt = ede.data->frag_id;
- if (dist_seq_rbt_lookup_insert(&dep->sequences, seq) != NULL) {
+ erts_de_rlock(dep);
+ if (dep->state != ERTS_DE_STATE_CONNECTED
+ || dep->connection_id != ede.connection_id
+ || dist_seq_rbt_lookup_insert(&dep->sequences, seq) != NULL) {
free_message_buffer(&seq->hfrag);
- goto data_error;
+ goto data_error_runlock;
}
+ erts_de_runlock(dep);
erts_make_dist_ext_copy(&ede, erts_get_dist_ext(&seq->hfrag));
@@ -1968,10 +1972,17 @@ int erts_net_message(Port *prt,
/* fall through, the first fragment in the sequence was the last fragment */
case ERTS_PREP_DIST_EXT_FRAG_CONT: {
- DistSeqNode *seq = dist_seq_rbt_lookup(dep->sequences, ede.data->seq_id);
+ DistSeqNode *seq;
+ erts_de_rlock(dep);
+ if (dep->state != ERTS_DE_STATE_CONNECTED
+ || dep->connection_id != ede.connection_id) {
+ goto data_error_runlock;
+ }
+
+ seq = dist_seq_rbt_lookup(dep->sequences, ede.data->seq_id);
if (!seq)
- goto data_error;
+ goto data_error_runlock;
/* If we did a fall-though we already did this */
if (res == ERTS_PREP_DIST_EXT_FRAG_CONT)
@@ -1979,16 +1990,20 @@ int erts_net_message(Port *prt,
/* Verify that the fragments have arrived in the correct order */
if (seq->cnt != ede.data->frag_id)
- goto data_error;
+ goto data_error_runlock;
seq->cnt--;
/* Check if this was the last fragment */
- if (ede.data->frag_id > 1)
+ if (ede.data->frag_id > 1) {
+ erts_de_runlock(dep);
return 0;
+ }
/* Last fragment arrived, time to dispatch the signal */
+
dist_seq_rbt_delete(&dep->sequences, seq);
+ erts_de_runlock(dep);
ctl_len = seq->ctl_len;
/* Now that we no longer need the DistSeqNode we re-use the heapfragment
@@ -2352,7 +2367,7 @@ int erts_net_message(Port *prt,
* the atom '' (empty cookie).
*/
ASSERT((type == DOP_SEND_SENDER || type == DOP_SEND_SENDER_TT)
- ? (is_pid(tuple[2]) && (dep->dflags & DFLAG_SEND_SENDER))
+ ? is_pid(tuple[2])
: tuple[2] == am_Empty);
#ifdef ERTS_DIST_MSG_DBG
@@ -2810,7 +2825,7 @@ int erts_net_message(Port *prt,
*/
dist_pend_spawn_exit_save_child_result(result,
ref,
- dep->mld);
+ ede.mld);
}
}
else if (lnk && !link_inserted) {
@@ -2856,6 +2871,9 @@ data_error:
erts_kill_dist_connection(dep, conn_id);
ERTS_CHK_NO_PROC_LOCKS;
return -1;
+data_error_runlock:
+ erts_de_runlock(dep);
+ goto data_error;
}
static int dsig_send_exit(ErtsDSigSendContext *ctx, Eterm ctl, Eterm msg)
--
2.35.3