From d8365e0f0f6960ef2c6a4011d3f372ccda3b4d7f Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 4 Aug 2023 13:50:10 -0400 Subject: [PATCH] kernel/event_queue: Only set B_EVENT_INVALID with the lock held. The dequeue routine expects that if B_EVENT_INVALID is set, it is free to delete the object. So we must only set it with the lock held, so that by the time the dequeue routine sees it, we will be done with the event. --- src/system/kernel/events/event_queue.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/events/event_queue.cpp b/src/system/kernel/events/event_queue.cpp index 83107e2f23..b42aaf7432 100644 --- a/src/system/kernel/events/event_queue.cpp +++ b/src/system/kernel/events/event_queue.cpp @@ -341,7 +341,7 @@ EventQueue::_Notify(select_event* event, uint16 events) if ((events & event->selected_events) == 0) return; - const int32 previousEvents = atomic_or(&event->events, events); + const int32 previousEvents = atomic_or(&event->events, (events & ~B_EVENT_INVALID)); // If the event is already being deleted, we should ignore this notification. if ((previousEvents & B_EVENT_DELETING) != 0) @@ -362,8 +362,10 @@ EventQueue::_Notify(select_event* event, uint16 events) // If we get B_EVENT_INVALID it means the object we were monitoring was // deleted. The object's ID may now be reused, so we must remove it // from the event tree. - if ((events & B_EVENT_INVALID) != 0) + if ((events & B_EVENT_INVALID) != 0) { + atomic_or(&event->events, B_EVENT_INVALID); fEventTree.Remove(event); + } // If it's not already queued, it's our responsibility to queue it. if ((atomic_or(&event->events, B_EVENT_QUEUED) & B_EVENT_QUEUED) == 0) {