From 8b0b6534719ca7e609fb2b73e49eb6064d9f8943 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 2 Aug 2020 19:34:09 -0600 Subject: [PATCH] LibIPC: Fix waiting for specific message When waiting for a specific message, only consider messages from the peer endpoint. Otherwise a message with the same id for the local endpoint may be misinterpreted. This fixes the Terminal sometimes hanging after bootup because a local endpoint message is mistaken for the CreateMenuResponse message. --- Libraries/LibIPC/ServerConnection.h | 54 ++++++++++++++++------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/Libraries/LibIPC/ServerConnection.h b/Libraries/LibIPC/ServerConnection.h index c86968d3a90..1556b309dd8 100644 --- a/Libraries/LibIPC/ServerConnection.h +++ b/Libraries/LibIPC/ServerConnection.h @@ -83,29 +83,7 @@ public: template OwnPtr wait_for_specific_message() { - // Double check we don't already have the event waiting for us. - // Otherwise we might end up blocked for a while for no reason. - for (size_t i = 0; i < m_unprocessed_messages.size(); ++i) { - if (m_unprocessed_messages[i].message_id() == MessageType::static_message_id()) - return m_unprocessed_messages.take(i).template release_nonnull(); - } - for (;;) { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(m_connection->fd(), &rfds); - int rc = Core::safe_syscall(select, m_connection->fd() + 1, &rfds, nullptr, nullptr, nullptr); - if (rc < 0) { - perror("select"); - } - ASSERT(rc > 0); - ASSERT(FD_ISSET(m_connection->fd(), &rfds)); - if (!drain_messages_from_server()) - return nullptr; - for (size_t i = 0; i < m_unprocessed_messages.size(); ++i) { - if (m_unprocessed_messages[i].message_id() == MessageType::static_message_id()) - return m_unprocessed_messages.take(i).template release_nonnull(); - } - } + return wait_for_specific_endpoint_message(); } bool post_message(const Message& message) @@ -126,12 +104,40 @@ public: { bool success = post_message(RequestType(forward(args)...)); ASSERT(success); - auto response = wait_for_specific_message(); + auto response = wait_for_specific_endpoint_message(); ASSERT(response); return response; } private: + template + OwnPtr wait_for_specific_endpoint_message() + { + for (;;) { + // Double check we don't already have the event waiting for us. + // Otherwise we might end up blocked for a while for no reason. + for (size_t i = 0; i < m_unprocessed_messages.size(); ++i) { + auto& message = m_unprocessed_messages[i]; + if (message.endpoint_magic() != Endpoint::static_magic()) + continue; + if (message.message_id() == MessageType::static_message_id()) + return m_unprocessed_messages.take(i).template release_nonnull(); + } + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(m_connection->fd(), &rfds); + int rc = Core::safe_syscall(select, m_connection->fd() + 1, &rfds, nullptr, nullptr, nullptr); + if (rc < 0) { + perror("select"); + } + ASSERT(rc > 0); + ASSERT(FD_ISSET(m_connection->fd(), &rfds)); + if (!drain_messages_from_server()) + return nullptr; + } + } + bool drain_messages_from_server() { Vector bytes;