From 606df46e46de63d030104ee61cfa99e4bce036b1 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 28 Apr 2024 12:15:40 -0400 Subject: [PATCH] Ladybird/AppKit: Retrieve socket notifiers from the local thread data For some reason, we occasionally receive a junk `info` pointer from the CFSocketCallback we create for socket notifiers. Instead of capturing a pointer to the local Core::Notifier for this `info` member, grab it from the thread data instance based on the socket FD. This was mostly seen when spamming new window requests to an existing Ladybird process. --- .../Application/EventLoopImplementation.mm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Ladybird/AppKit/Application/EventLoopImplementation.mm b/Ladybird/AppKit/Application/EventLoopImplementation.mm index 0031e037ced..152ff444777 100644 --- a/Ladybird/AppKit/Application/EventLoopImplementation.mm +++ b/Ladybird/AppKit/Application/EventLoopImplementation.mm @@ -23,6 +23,17 @@ struct ThreadData { return s_thread_data; } + Core::Notifier& notifier_by_fd(int fd) + { + for (auto notifier : notifiers) { + if (notifier.key->fd() == fd) + return *notifier.key; + } + + // If we didn't have a notifier for the provided FD, it should have been unregistered. + VERIFY_NOT_REACHED(); + } + IDAllocator timer_id_allocator; HashMap timers; HashMap notifiers; @@ -93,9 +104,9 @@ void CFEventLoopManager::unregister_timer(intptr_t timer_id) CFRelease(*timer); } -static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notification_type, CFDataRef, void const*, void* info) +static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notification_type, CFDataRef, void const*, void*) { - auto& notifier = *reinterpret_cast(info); + auto& notifier = ThreadData::the().notifier_by_fd(CFSocketGetNative(socket)); // This socket callback is not quite re-entrant. If Core::Notifier::dispatch_event blocks, e.g. // to wait upon a Core::Promise, this socket will not receive any more notifications until that @@ -127,7 +138,7 @@ void CFEventLoopManager::register_notifier(Core::Notifier& notifier) break; } - CFSocketContext context { .version = 0, .info = ¬ifier, .retain = nullptr, .release = nullptr, .copyDescription = nullptr }; + CFSocketContext context { .version = 0, .info = nullptr, .retain = nullptr, .release = nullptr, .copyDescription = nullptr }; auto* socket = CFSocketCreateWithNative(kCFAllocatorDefault, notifier.fd(), notification_type, &socket_notifier, &context); CFOptionFlags sockopt = CFSocketGetSocketFlags(socket);