From c5ff57c59cba41341172d6e8c4d3605cfbba4064 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 16 Dec 2024 20:05:19 +0100 Subject: [PATCH] sys/event: fix race in event_wait_multi() We need to clear `event->next` while IRQs are still disabled to avoid another thread from calling `event_cancel()` just in-between. --- sys/event/event.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sys/event/event.c b/sys/event/event.c index e9bd1ce313af..7a1a8e09cd7b 100644 --- a/sys/event/event.c +++ b/sys/event/event.c @@ -90,7 +90,7 @@ event_t *event_wait_multi(event_queue_t *queues, size_t n_queues) assert(queues && n_queues); event_t *result = NULL; - do { + while (1) { unsigned state = irq_disable(); for (size_t i = 0; i < n_queues; i++) { assert(queues[i].waiter); @@ -100,14 +100,16 @@ event_t *event_wait_multi(event_queue_t *queues, size_t n_queues) break; } } - irq_restore(state); - if (result == NULL) { - thread_flags_wait_any(THREAD_FLAG_EVENT); + + if (result != NULL) { + result->list_node.next = NULL; + irq_restore(state); + return result; } - } while (result == NULL); - result->list_node.next = NULL; - return result; + irq_restore(state); + thread_flags_wait_any(THREAD_FLAG_EVENT); + } } #if IS_USED(MODULE_XTIMER) || IS_USED(MODULE_ZTIMER)