From d2f1516818387d90b8973e0b752c9012bb17fec7 Mon Sep 17 00:00:00 2001 From: pajlada Date: Sat, 1 Jul 2023 14:01:47 +0200 Subject: [PATCH] Fix crash that could occur if closing the usercard quickly after blocking (#4711) * Specifically, this adds a caller to the network request, which makes the success or failure callback not fire. This has the unintended consequence of the block list not reloading if the usercard is closed, but it's not a big concern. * Add unrelated `-DUSE_ALTERNATE_LINKER` cmake option From https://github.com/heavyai/heavydb/blob/0517d99b467806f6af7b4c969e351368a667497d/CMakeLists.txt#L87-L103 --- CHANGELOG.md | 2 ++ CMakeLists.txt | 21 +++++++++++++++++++ mocks/include/mocks/Helix.hpp | 6 ++++-- .../commands/CommandController.cpp | 4 ++-- src/providers/twitch/TwitchAccount.cpp | 10 +++++---- src/providers/twitch/TwitchAccount.hpp | 7 +++++-- src/providers/twitch/api/Helix.cpp | 6 ++++-- src/providers/twitch/api/Helix.hpp | 9 ++++---- src/widgets/dialogs/UserInfoPopup.cpp | 5 +++-- 9 files changed, 52 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b8281b..d5b6f3b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Bugfix: Fix visual glitches with smooth scrolling. (#4501) - Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698) - Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702) +- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711) - Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637) - Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570) - Dev: Added test cases for emote and tab completion. (#4644) @@ -30,6 +31,7 @@ - Dev: Added `sccache` in Windows CI. (#4678) - Dev: Moved preprocessor Git and date definitions to executables only. (#4681) - Dev: Refactored tests to be able to use `ctest` and run in debug builds. (#4700) +- Dev: Added the ability to use an alternate linker using the `-DUSE_ALTERNATE_LINKER=...` CMake parameter. (#4711) ## 2.4.4 diff --git a/CMakeLists.txt b/CMakeLists.txt index af05f742..db82c9ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,27 @@ elseif (CCACHE_PROGRAM) set(_compiler_launcher ${CCACHE_PROGRAM}) endif () + +# Alternate linker code taken from heavyai/heavydb +# https://github.com/heavyai/heavydb/blob/0517d99b467806f6af7b4c969e351368a667497d/CMakeLists.txt#L87-L103 +macro(set_alternate_linker linker) + find_program(LINKER_EXECUTABLE ld.${USE_ALTERNATE_LINKER} ${USE_ALTERNATE_LINKER}) + if(LINKER_EXECUTABLE) + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 12.0.0) + add_link_options("-ld-path=${USE_ALTERNATE_LINKER}") + else() + add_link_options("-fuse-ld=${USE_ALTERNATE_LINKER}") + endif() + else() + set(USE_ALTERNATE_LINKER "" CACHE STRING "Use alternate linker" FORCE) + endif() +endmacro() + +set(USE_ALTERNATE_LINKER "" CACHE STRING "Use alternate linker. Leave empty for system default; alternatives are 'gold', 'lld', 'bfd', 'mold'") +if(NOT "${USE_ALTERNATE_LINKER}" STREQUAL "") + set_alternate_linker(${USE_ALTERNATE_LINKER}) +endif() + if (_compiler_launcher) set(CMAKE_CXX_COMPILER_LAUNCHER "${_compiler_launcher}" CACHE STRING "CXX compiler launcher") message(STATUS "Using ${_compiler_launcher} for speeding up build") diff --git a/mocks/include/mocks/Helix.hpp b/mocks/include/mocks/Helix.hpp index e7fe4ef4..45b1017e 100644 --- a/mocks/include/mocks/Helix.hpp +++ b/mocks/include/mocks/Helix.hpp @@ -105,12 +105,14 @@ public: (override)); MOCK_METHOD(void, blockUser, - (QString targetUserId, std::function successCallback, + (QString targetUserId, const QObject *caller, + std::function successCallback, HelixFailureCallback failureCallback), (override)); MOCK_METHOD(void, unblockUser, - (QString targetUserId, std::function successCallback, + (QString targetUserId, const QObject *caller, + std::function successCallback, HelixFailureCallback failureCallback), (override)); diff --git a/src/controllers/commands/CommandController.cpp b/src/controllers/commands/CommandController.cpp index 3956ec9c..bd282224 100644 --- a/src/controllers/commands/CommandController.cpp +++ b/src/controllers/commands/CommandController.cpp @@ -650,7 +650,7 @@ void CommandController::initialize(Settings &, Paths &paths) target, [currentUser, channel, target](const HelixUser &targetUser) { getApp()->accounts->twitch.getCurrent()->blockUser( - targetUser.id, + targetUser.id, nullptr, [channel, target, targetUser] { channel->addMessage(makeSystemMessage( QString("You successfully blocked user %1") @@ -703,7 +703,7 @@ void CommandController::initialize(Settings &, Paths &paths) target, [currentUser, channel, target](const auto &targetUser) { getApp()->accounts->twitch.getCurrent()->unblockUser( - targetUser.id, + targetUser.id, nullptr, [channel, target, targetUser] { channel->addMessage(makeSystemMessage( QString("You successfully unblocked user %1") diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 789ed833..0830fa15 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -121,11 +121,12 @@ void TwitchAccount::loadBlocks() }); } -void TwitchAccount::blockUser(QString userId, std::function onSuccess, +void TwitchAccount::blockUser(QString userId, const QObject *caller, + std::function onSuccess, std::function onFailure) { getHelix()->blockUser( - userId, + userId, caller, [this, userId, onSuccess] { TwitchUser blockedUser; blockedUser.id = userId; @@ -141,11 +142,12 @@ void TwitchAccount::blockUser(QString userId, std::function onSuccess, std::move(onFailure)); } -void TwitchAccount::unblockUser(QString userId, std::function onSuccess, +void TwitchAccount::unblockUser(QString userId, const QObject *caller, + std::function onSuccess, std::function onFailure) { getHelix()->unblockUser( - userId, + userId, caller, [this, userId, onSuccess] { TwitchUser ignoredUser; ignoredUser.id = userId; diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index 7e4b69d2..154d307f 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -71,9 +72,11 @@ public: bool isAnon() const; void loadBlocks(); - void blockUser(QString userId, std::function onSuccess, + void blockUser(QString userId, const QObject *caller, + std::function onSuccess, std::function onFailure); - void unblockUser(QString userId, std::function onSuccess, + void unblockUser(QString userId, const QObject *caller, + std::function onSuccess, std::function onFailure); SharedAccessGuard> accessBlockedUserIds() const; diff --git a/src/providers/twitch/api/Helix.cpp b/src/providers/twitch/api/Helix.cpp index 59329ae5..b22e2066 100644 --- a/src/providers/twitch/api/Helix.cpp +++ b/src/providers/twitch/api/Helix.cpp @@ -541,7 +541,7 @@ void Helix::loadBlocks(QString userId, .execute(); } -void Helix::blockUser(QString targetUserId, +void Helix::blockUser(QString targetUserId, const QObject *caller, std::function successCallback, HelixFailureCallback failureCallback) { @@ -549,6 +549,7 @@ void Helix::blockUser(QString targetUserId, urlQuery.addQueryItem("target_user_id", targetUserId); this->makePut("users/blocks", urlQuery) + .caller(caller) .onSuccess([successCallback](auto /*result*/) -> Outcome { successCallback(); return Success; @@ -560,7 +561,7 @@ void Helix::blockUser(QString targetUserId, .execute(); } -void Helix::unblockUser(QString targetUserId, +void Helix::unblockUser(QString targetUserId, const QObject *caller, std::function successCallback, HelixFailureCallback failureCallback) { @@ -568,6 +569,7 @@ void Helix::unblockUser(QString targetUserId, urlQuery.addQueryItem("target_user_id", targetUserId); this->makeDelete("users/blocks", urlQuery) + .caller(caller) .onSuccess([successCallback](auto /*result*/) -> Outcome { successCallback(); return Success; diff --git a/src/providers/twitch/api/Helix.hpp b/src/providers/twitch/api/Helix.hpp index 3a370a41..79ff59d6 100644 --- a/src/providers/twitch/api/Helix.hpp +++ b/src/providers/twitch/api/Helix.hpp @@ -805,12 +805,12 @@ public: HelixFailureCallback failureCallback) = 0; // https://dev.twitch.tv/docs/api/reference#block-user - virtual void blockUser(QString targetUserId, + virtual void blockUser(QString targetUserId, const QObject *caller, std::function successCallback, HelixFailureCallback failureCallback) = 0; // https://dev.twitch.tv/docs/api/reference#unblock-user - virtual void unblockUser(QString targetUserId, + virtual void unblockUser(QString targetUserId, const QObject *caller, std::function successCallback, HelixFailureCallback failureCallback) = 0; @@ -1118,11 +1118,12 @@ public: HelixFailureCallback failureCallback) final; // https://dev.twitch.tv/docs/api/reference#block-user - void blockUser(QString targetUserId, std::function successCallback, + void blockUser(QString targetUserId, const QObject *caller, + std::function successCallback, HelixFailureCallback failureCallback) final; // https://dev.twitch.tv/docs/api/reference#unblock-user - void unblockUser(QString targetUserId, + void unblockUser(QString targetUserId, const QObject *caller, std::function successCallback, HelixFailureCallback failureCallback) final; diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index e6978100..e5955884 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -36,6 +36,7 @@ #include #include #include +#include const QString TEXT_FOLLOWERS("Followers: %1"); const QString TEXT_CREATED("Created: %1"); @@ -593,7 +594,7 @@ void UserInfoPopup::installEvents() this->ui_.block->setEnabled(false); getApp()->accounts->twitch.getCurrent()->unblockUser( - this->userId_, + this->userId_, this, [this, reenableBlockCheckbox, currentUser] { this->channel_->addMessage(makeSystemMessage( QString("You successfully unblocked user %1") @@ -620,7 +621,7 @@ void UserInfoPopup::installEvents() this->ui_.block->setEnabled(false); getApp()->accounts->twitch.getCurrent()->blockUser( - this->userId_, + this->userId_, this, [this, reenableBlockCheckbox, currentUser] { this->channel_->addMessage(makeSystemMessage( QString("You successfully blocked user %1")