From 0ce541b6ea704483ddb62152e6edd71a5edb9f08 Mon Sep 17 00:00:00 2001 From: Zephyron Date: Fri, 21 Nov 2025 17:29:21 +1000 Subject: [PATCH] Fix multiplayer chat room signal disconnection and cleanup - Add Shutdown() method to ChatRoom to properly disconnect Qt signals - Initialize room_network pointer to nullptr for safety - Call Shutdown() in MultiplayerRoomOverlay::DisconnectFromRoom() to prevent signal leaks when disconnecting from rooms - Ensures proper cleanup of chat widget connections when overlay is hidden Signed-off-by: Zephyron --- src/citron/multiplayer/chat_room.cpp | 16 ++++++++++++++++ src/citron/multiplayer/chat_room.h | 3 ++- src/citron/util/multiplayer_room_overlay.cpp | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/citron/multiplayer/chat_room.cpp b/src/citron/multiplayer/chat_room.cpp index e71cc9140..324034e7b 100644 --- a/src/citron/multiplayer/chat_room.cpp +++ b/src/citron/multiplayer/chat_room.cpp @@ -221,6 +221,22 @@ void ChatRoom::Initialize(Network::RoomNetwork* room_network_) { } } +void ChatRoom::Shutdown() { + if (room_network) { + // Disconnect the signals that were connected in Initialize. + // It's safe to call disconnect even if the connection doesn't exist. + disconnect(this, &ChatRoom::ChatReceived, this, &ChatRoom::OnChatReceive); + disconnect(this, &ChatRoom::StatusMessageReceived, this, &ChatRoom::OnStatusMessageReceive); + + // NOTE: The Bind... functions do not have a direct unbind. The intended way + // to stop them is to let the 'member' object be destroyed or to stop calling them + // from the network backend. Since we are disconnecting from the room, this is safe. + // The important part is disconnecting the Qt signals. + + room_network = nullptr; // Clear the pointer to prevent further use. + } +} + void ChatRoom::SetModPerms(bool is_mod) { has_mod_perms = is_mod; } diff --git a/src/citron/multiplayer/chat_room.h b/src/citron/multiplayer/chat_room.h index 5283f2a1d..c6277cdf7 100644 --- a/src/citron/multiplayer/chat_room.h +++ b/src/citron/multiplayer/chat_room.h @@ -32,6 +32,7 @@ class ChatRoom : public QWidget { public: explicit ChatRoom(QWidget* parent); void Initialize(Network::RoomNetwork* room_network); + void Shutdown(); void RetranslateUi(); void SetPlayerList(const Network::RoomMember::MemberList& member_list); void Clear(); @@ -68,7 +69,7 @@ private: std::unique_ptr ui; std::unordered_set block_list; std::unordered_map icon_cache; - Network::RoomNetwork* room_network; + Network::RoomNetwork* room_network = nullptr; // Initialize to nullptr }; Q_DECLARE_METATYPE(Network::ChatEntry); diff --git a/src/citron/util/multiplayer_room_overlay.cpp b/src/citron/util/multiplayer_room_overlay.cpp index 484cccb38..f5666b322 100644 --- a/src/citron/util/multiplayer_room_overlay.cpp +++ b/src/citron/util/multiplayer_room_overlay.cpp @@ -188,6 +188,12 @@ void MultiplayerRoomOverlay::ConnectToRoom() { } void MultiplayerRoomOverlay::DisconnectFromRoom() { + // Tell the chat widget to disconnect its signals *before* + // we reset our own state. + if (is_chat_initialized && chat_room_widget) { + chat_room_widget->Shutdown(); + } + ClearUI(); room_member.reset(); multiplayer_state = nullptr;