Skip to content

Commit 4497a42

Browse files
committed
fix
Signed-off-by: Peter M <petermm@gmail.com>
1 parent 0109ff7 commit 4497a42

File tree

1 file changed

+6
-25
lines changed

1 file changed

+6
-25
lines changed

src/libAtomVM/dist_nifs.c

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -122,47 +122,28 @@ static void dist_connection_dtor(ErlNifEnv *caller_env, void *obj)
122122
enif_demonitor_process(caller_env, conn_obj, &conn_obj->connection_process_monitor);
123123
}
124124

125-
// Collect monitors to demonitor outside the lock to avoid holding lock
126-
// across potentially blocking enif_demonitor_process calls
127-
struct ListHead monitors_to_free;
128-
list_init(&monitors_to_free);
129-
125+
// Must hold lock while calling enif_demonitor_process to prevent race
126+
// with dist_connection_down callback
130127
struct ListHead *remote_monitors = synclist_wrlock(&conn_obj->remote_monitors);
131128
struct ListHead *item;
132129
struct ListHead *tmp;
133130
MUTABLE_LIST_FOR_EACH (item, tmp, remote_monitors) {
134-
list_remove(item);
135-
list_append(&monitors_to_free, item);
136-
}
137-
synclist_unlock(&conn_obj->remote_monitors);
138-
synclist_destroy(&conn_obj->remote_monitors);
139-
140-
// Now demonitor and free outside the lock
141-
MUTABLE_LIST_FOR_EACH (item, tmp, &monitors_to_free) {
142131
struct RemoteMonitor *remote_monitor = GET_LIST_ENTRY(item, struct RemoteMonitor, head);
143132
enif_demonitor_process(caller_env, conn_obj, &remote_monitor->process_monitor);
144133
list_remove(item);
145134
free(remote_monitor);
146135
}
147-
148-
// Collect packets to free outside the lock
149-
struct ListHead packets_to_free;
150-
list_init(&packets_to_free);
136+
synclist_unlock(&conn_obj->remote_monitors);
137+
synclist_destroy(&conn_obj->remote_monitors);
151138

152139
struct ListHead *pending_packets = synclist_wrlock(&conn_obj->pending_packets);
153140
MUTABLE_LIST_FOR_EACH (item, tmp, pending_packets) {
154-
list_remove(item);
155-
list_append(&packets_to_free, item);
156-
}
157-
synclist_unlock(&conn_obj->pending_packets);
158-
synclist_destroy(&conn_obj->pending_packets);
159-
160-
// Free packets outside the lock
161-
MUTABLE_LIST_FOR_EACH (item, tmp, &packets_to_free) {
162141
struct DistributionPacket *packet = GET_LIST_ENTRY(item, struct DistributionPacket, head);
163142
list_remove(item);
164143
free(packet);
165144
}
145+
synclist_unlock(&conn_obj->pending_packets);
146+
synclist_destroy(&conn_obj->pending_packets);
166147
}
167148

168149
static void dist_enqueue_message(term control_message, term payload, struct DistConnection *connection, GlobalContext *global)

0 commit comments

Comments
 (0)