From 0f9eb4beeb1d156d1b02c4a14f7dc6ae94f13fc5 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 27 Mar 2024 15:25:24 +0000 Subject: [PATCH] Fix logout current connection crash Make sure that the neochat can handle switching connection when the current one is logged out. This is mostly about using QPointer to handle use after free issues due to room objects being deleted. --- src/controller.cpp | 9 +++++++++ src/models/messageeventmodel.cpp | 4 ++++ src/models/messageeventmodel.h | 2 +- src/models/timelinemodel.h | 2 +- src/neochatconnection.cpp | 8 -------- src/notificationsmanager.cpp | 4 ++-- src/roommanager.h | 2 +- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/controller.cpp b/src/controller.cpp index 739b7af38..03c8b89bc 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -156,6 +156,15 @@ void Controller::addConnection(NeoChatConnection *c) c->saveState(); }); connect(c, &NeoChatConnection::loggedOut, this, [this, c] { + if (accounts().count() > 1) { + // Only set the connection if the the account being logged out is currently active + if (c == activeConnection()) { + setActiveConnection(dynamic_cast(accounts().accounts()[0])); + } + } else { + setActiveConnection(nullptr); + } + dropConnection(c); }); connect(c, &NeoChatConnection::badgeNotificationCountChanged, this, &Controller::updateBadgeNotificationCount); diff --git a/src/models/messageeventmodel.cpp b/src/models/messageeventmodel.cpp index 466253800..a7385c4ee 100644 --- a/src/models/messageeventmodel.cpp +++ b/src/models/messageeventmodel.cpp @@ -629,6 +629,10 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const int MessageEventModel::eventIdToRow(const QString &eventID) const { + if (m_currentRoom == nullptr) { + return -1; + } + const auto it = m_currentRoom->findInTimeline(eventID); if (it == m_currentRoom->historyEdge()) { // qWarning() << "Trying to find inexistent event:" << eventID; diff --git a/src/models/messageeventmodel.h b/src/models/messageeventmodel.h index 253a8fac7..203162b4a 100644 --- a/src/models/messageeventmodel.h +++ b/src/models/messageeventmodel.h @@ -113,7 +113,7 @@ private Q_SLOTS: void refreshRow(int row); private: - NeoChatRoom *m_currentRoom = nullptr; + QPointer m_currentRoom = nullptr; QString lastReadEventId; QPersistentModelIndex m_lastReadEventIndex; int rowBelowInserted = -1; diff --git a/src/models/timelinemodel.h b/src/models/timelinemodel.h index 1c8f993ba..714ee0919 100644 --- a/src/models/timelinemodel.h +++ b/src/models/timelinemodel.h @@ -61,7 +61,7 @@ public: [[nodiscard]] QHash roleNames() const override; private: - NeoChatRoom *m_room = nullptr; + QPointer m_room = nullptr; }; /** diff --git a/src/neochatconnection.cpp b/src/neochatconnection.cpp index 57de03a2c..694d78d6f 100644 --- a/src/neochatconnection.cpp +++ b/src/neochatconnection.cpp @@ -153,14 +153,6 @@ void NeoChatConnection::logout(bool serverSideLogout) job.start(); loop.exec(); - if (Controller::instance().accounts().count() > 1) { - // Only set the connection if the the account being logged out is currently active - if (this == Controller::instance().activeConnection()) { - Controller::instance().setActiveConnection(dynamic_cast(Controller::instance().accounts().accounts()[0])); - } - } else { - Controller::instance().setActiveConnection(nullptr); - } if (!serverSideLogout) { return; } diff --git a/src/notificationsmanager.cpp b/src/notificationsmanager.cpp index 9dd5dadfb..ace9fe52e 100644 --- a/src/notificationsmanager.cpp +++ b/src/notificationsmanager.cpp @@ -57,7 +57,7 @@ void NotificationsManager::processNotificationJob(QPointer co if (job == nullptr) { return; } - if (connection == nullptr) { + if (connection == nullptr || !connection->isLoggedIn()) { qWarning() << QStringLiteral("No connection for GetNotificationsJob %1").arg(job->objectName()); return; } @@ -150,7 +150,7 @@ void NotificationsManager::processNotificationJob(QPointer co bool NotificationsManager::shouldPostNotification(QPointer connection, const QJsonValue ¬ification) { - if (connection == nullptr) { + if (connection == nullptr || !connection->isLoggedIn()) { return false; } diff --git a/src/roommanager.h b/src/roommanager.h index 289cb217f..c9107d9c4 100644 --- a/src/roommanager.h +++ b/src/roommanager.h @@ -340,7 +340,7 @@ Q_SIGNALS: private: void openRoomForActiveConnection(); - NeoChatRoom *m_currentRoom; + QPointer m_currentRoom; NeoChatRoom *m_lastCurrentRoom; QString m_arg; KSharedConfig::Ptr m_config;