From af671f58ed0845bcab9a75b55caaa79fe2a867d3 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 8 Jul 2025 07:34:28 -0400 Subject: [PATCH] LibCore: Revert change to simplify tracking of notifers and poll structs The issue with that refactor was that the same fd can be used in more than one notifier. This reverts us back to using 2 members to track the notifiers in play. --- .../LibCore/EventLoopImplementationUnix.cpp | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Libraries/LibCore/EventLoopImplementationUnix.cpp b/Libraries/LibCore/EventLoopImplementationUnix.cpp index 962b6291ed1..300ebce9a78 100644 --- a/Libraries/LibCore/EventLoopImplementationUnix.cpp +++ b/Libraries/LibCore/EventLoopImplementationUnix.cpp @@ -267,6 +267,7 @@ struct ThreadData { // The wake pipe informs us of POSIX signals as well as manual calls to wake() poll_fds.append({ .fd = wake_pipe_fds[0], .events = POLLIN, .revents = 0 }); + notifiers.append(nullptr); } ~ThreadData() @@ -279,7 +280,8 @@ struct ThreadData { // Each thread has its own timers, notifiers and a wake pipe. TimeoutSet timeouts; - HashMap notifiers; + HashMap notifier_to_index; + Vector notifiers; Vector poll_fds; // The wake pipe is used to notify another event loop that someone has called wake(), or a signal has been received. @@ -405,14 +407,14 @@ try_select_again: if (error_or_marked_fd_count.value() != 0) { // Handle file system notifiers by making them normal events. - for (auto const& poll_fd : thread_data.poll_fds.span().slice(1)) { - auto& notifier = *thread_data.notifiers.get(poll_fd.fd).value(); + for (size_t i = 1; i < thread_data.poll_fds.size(); ++i) { + auto& notifier = *thread_data.notifiers[i]; #ifdef AK_OS_ANDROID // FIXME: Make the check work under Android, perhaps use ALooper. ThreadEventQueue::current().post_event(notifier, make(notifier.fd(), notifier.type())); #else - auto revents = poll_fd.revents; + auto revents = thread_data.poll_fds[i].revents; NotificationType type = NotificationType::None; if (has_flag(revents, POLLIN)) @@ -650,7 +652,8 @@ void EventLoopManagerUnix::register_notifier(Notifier& notifier) { auto& thread_data = ThreadData::the(); - thread_data.notifiers.set(notifier.fd(), ¬ifier); + thread_data.notifier_to_index.set(¬ifier, thread_data.poll_fds.size()); + thread_data.notifiers.append(¬ifier); auto events = notification_type_to_poll_events(notifier.type()); thread_data.poll_fds.append({ .fd = notifier.fd(), .events = events, .revents = 0 }); @@ -664,11 +667,18 @@ void EventLoopManagerUnix::unregister_notifier(Notifier& notifier) if (!thread_data) return; - thread_data->notifiers.remove(notifier.fd()); + auto notifier_index = thread_data->notifier_to_index.take(¬ifier).release_value(); - thread_data->poll_fds.remove_all_matching([&](auto const& poll_fd) { - return poll_fd.fd == notifier.fd(); - }); + if (notifier_index + 1 < thread_data->poll_fds.size()) { + swap(thread_data->notifiers[notifier_index], thread_data->notifiers.last()); + swap(thread_data->poll_fds[notifier_index], thread_data->poll_fds.last()); + + auto* swapped_notifier = thread_data->notifiers[notifier_index]; + thread_data->notifier_to_index.set(swapped_notifier, notifier_index); + } + + thread_data->notifiers.take_last(); + thread_data->poll_fds.take_last(); } void EventLoopManagerUnix::did_post_event()