File 3241-erts-Fix-sigq-buffer-removal.patch of Package erlang
From 8511ce01c776ea9d50467cd83ef20d4cf5c646ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Thu, 3 Mar 2022 11:15:55 +0100
Subject: [PATCH 1/2] erts: Fix sigq buffer removal
The `nonmsg_slots` of the current buffer was not cleared after
flushing when the buffer was removed, breaking the flag handling
in `erts_proc_sig_fetch`.
---
erts/emulator/beam/erl_proc_sig_queue.c | 54 ++++++++++++++-----------
1 file changed, 30 insertions(+), 24 deletions(-)
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index 50492fa24f..5eb9904067 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -8240,23 +8240,28 @@ erts_proc_sig_queue_flush_get_buffers(Process* proc, int *need_unget_buffers)
void
erts_proc_sig_queue_flush_buffers(Process* proc)
{
+ ErtsSignalInQueueBufferArray* buffers;
int need_undread_buffers;
- ErtsSignalInQueueBufferArray* buffers =
+
+ ERTS_LC_ASSERT(ERTS_PROC_IS_EXITING(proc) ||
+ (erts_proc_lc_my_proc_locks(proc) & ERTS_PROC_LOCK_MSGQ));
+
+ buffers =
erts_proc_sig_queue_flush_get_buffers(proc, &need_undread_buffers);
erts_proc_sig_queue_unget_buffers(buffers, need_undread_buffers);
}
-static void do_sigq_buffer_array_refc_dec(void *buffers_p)
+static void sigq_buffer_array_refc_dec(void *buffers_p)
{
ErtsSignalInQueueBufferArray* buffers = buffers_p;
erts_proc_sig_queue_unget_buffers(buffers, 1);
}
-static void do_schedule_sigq_buffer_array_refc_dec(void *buffers_p)
+static void schedule_sigq_buffer_array_refc_dec(void *buffers_p)
{
ErtsSignalInQueueBufferArray* buffers = buffers_p;
- erts_schedule_thr_prgr_later_cleanup_op(do_sigq_buffer_array_refc_dec,
+ erts_schedule_thr_prgr_later_cleanup_op(sigq_buffer_array_refc_dec,
buffers,
&buffers->free_item,
sizeof(ErtsSignalInQueueBufferArray));
@@ -8268,52 +8273,53 @@ void erts_proc_sig_queue_flush_and_deinstall_buffers(Process* proc)
ErtsSignalInQueueBufferArray* buffers;
int need_unget_buffers;
ErtsSchedulerData *esdp;
+
ERTS_LC_ASSERT(ERTS_PROC_IS_EXITING(proc) ||
(erts_proc_lc_my_proc_locks(proc) & ERTS_PROC_LOCK_MSGQ));
buffers = erts_proc_sig_queue_get_buffers(proc, &need_unget_buffers);
+
if (buffers == NULL) {
return;
}
+
if (!buffers->alive) {
erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);;
return;
}
+
buffers->alive = 0;
proc->sig_inq_contention_counter = 0;
+
for (i = 0; i < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; i++) {
proc_sig_queue_lock_buffer(&buffers->slots[i]);
+
if (buffers->slots[i].b.queue.first != NULL) {
sig_inq_concat(&proc->sig_inq, &buffers->slots[i].b.queue);
}
+
buffers->slots[i].b.alive = 0;
+
proc_sig_queue_unlock_buffer(&buffers->slots[i]);
}
- /*
- * Nothing can be enqueued to the buffer array any more
- */
+
+ /* Nothing can be enqueued to the buffer array beyond this point. */
+
+ erts_atomic64_set_nob(&buffers->nonempty_slots, (erts_aint64_t)0);
+ erts_atomic64_set_nob(&buffers->nonmsg_slots, (erts_aint64_t)0);
erts_atomic_set_mb(&proc->sig_inq_buffers, (erts_aint_t)NULL);
+
erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);
- /*
- * We should now do an additional reference count decrement to
- * force an eventiuall free of buffer array but we need to do that
- * after a thread progress period because an unmanaged thread
- * might be sleeping just before it will increment the reference
- * count.
- */
+
+ /* Release the buffer array through thread progress, as a managed thread
+ * may be holding a reference to it. */
esdp = erts_get_scheduler_data();
if (esdp != NULL && esdp->type == ERTS_SCHED_NORMAL) {
- erts_schedule_thr_prgr_later_cleanup_op(do_sigq_buffer_array_refc_dec,
- buffers,
- &buffers->free_item,
- sizeof(ErtsSignalInQueueBufferArray));
+ schedule_sigq_buffer_array_refc_dec((void*)buffers);
} else {
- /*
- * We cannot schedule a thread progress later cleanup
- * operation from an unmanaged thread so we schedule
- * that task to be run on a managed thread.
- */
+ /* We can't issue cleanup jobs on anything other than normal
+ * schedulers, so we move to the first scheduler if required. */
erts_schedule_misc_aux_work(1,
- do_schedule_sigq_buffer_array_refc_dec,
+ schedule_sigq_buffer_array_refc_dec,
buffers);
}
}
--
2.34.1