From d8df07625aec624f12377e05554387cdfeef33df Mon Sep 17 00:00:00 2001
From: dec05eba <dec05eba@protonmail.com>
Date: Fri, 21 May 2021 02:00:42 +0200
Subject: Fix deadlock by reference to stack local room outside the function

---
 plugins/Matrix.hpp     |  4 +++-
 src/plugins/Matrix.cpp | 35 +++++++++++++++++++----------------
 2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index 1c71733..ebaa166 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -164,7 +164,7 @@ namespace QuickMedia {
 
         size_t index = 0;
     private:
-        std::recursive_mutex user_mutex;
+        std::mutex user_mutex;
         std::recursive_mutex room_mutex;
 
         std::string name;
@@ -639,6 +639,8 @@ namespace QuickMedia {
         MatrixDelegate *delegate = nullptr;
         std::optional<std::string> filter_cached;
 
+        std::vector<std::unique_ptr<RoomData>> invite_rooms;
+
         std::unordered_set<std::string> my_events_transaction_ids;
     };
 }
\ No newline at end of file
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 0577948..15a7676 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -144,34 +144,34 @@ namespace QuickMedia {
     }
 
     void RoomData::set_user_read_marker(std::shared_ptr<UserInfo> &user, const std::string &event_id) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         user->read_marker_event_id = event_id;
     }
 
     std::string RoomData::get_user_read_marker(const std::shared_ptr<UserInfo> &user) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         return user->read_marker_event_id;
     }
 
     std::string RoomData::get_user_display_name(const std::shared_ptr<UserInfo> &user) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         return user->display_name;
     }
 
     std::string RoomData::get_user_avatar_url(const std::shared_ptr<UserInfo> &user) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         return user->avatar_url;
     }
 
     void RoomData::set_user_display_name(std::shared_ptr<UserInfo> &user, std::string display_name) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         user->display_name = std::move(display_name);
         if(user->display_name.empty())
             user->display_name = user->user_id;
     }
 
     void RoomData::set_user_avatar_url(std::shared_ptr<UserInfo> &user, std::string avatar_url) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         user->avatar_url = std::move(avatar_url);
     }
 
@@ -218,7 +218,7 @@ namespace QuickMedia {
     }
 
     std::vector<std::shared_ptr<UserInfo>> RoomData::get_users() {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         std::vector<std::shared_ptr<UserInfo>> users(user_info_by_user_id.size());
         size_t i = 0;
         for(auto &[user_id, user] : user_info_by_user_id) {
@@ -228,7 +228,7 @@ namespace QuickMedia {
     }
 
     std::vector<std::shared_ptr<UserInfo>> RoomData::get_users_excluding_me(const std::string &my_user_id) {
-        std::lock_guard<std::recursive_mutex> lock(user_mutex);
+        std::lock_guard<std::mutex> lock(user_mutex);
         std::vector<std::shared_ptr<UserInfo>> users_excluding_me;
         for(auto &[user_id, user] : user_info_by_user_id) {
             if(user->user_id != my_user_id) {
@@ -323,7 +323,7 @@ namespace QuickMedia {
 
     void RoomData::clear_data() {
         std::lock_guard<std::recursive_mutex> room_lock(room_mutex);
-        std::lock_guard<std::recursive_mutex> user_lock(user_mutex);
+        std::lock_guard<std::mutex> user_lock(user_mutex);
         //fetched_messages_by_event_id.clear();
         //userdata = nullptr;
         //user_info_by_user_id.clear();
@@ -2659,17 +2659,20 @@ namespace QuickMedia {
                     // TODO: Check this this room should be saved in the rooms list, which might be needed if the server doesn't give a non-invite events
                     // for the same data (user display name update, etc)
                     Invite invite;
-                    RoomData invite_room;
-                    events_add_user_info(events_json, &invite_room);
-                    events_set_room_info(events_json, &invite_room);
+                    auto invite_room = std::make_unique<RoomData>();
+                    RoomData *room = invite_room.get();
+                    invite_rooms.push_back(std::move(invite_room));
+
+                    events_add_user_info(events_json, room);
+                    events_set_room_info(events_json, room);
 
                     std::string sender_json_str(sender_json.GetString(), sender_json.GetStringLength());
-                    auto invited_by = get_user_by_id(&invite_room, sender_json_str);
+                    auto invited_by = get_user_by_id(room, sender_json_str);
 
-                    set_room_info_to_users_if_empty(&invite_room, sender_json_str);
+                    set_room_info_to_users_if_empty(room, sender_json_str);
 
-                    invite.room_name = invite_room.get_name();
-                    invite.room_avatar_url = invite_room.get_avatar_url();
+                    invite.room_name = room->get_name();
+                    invite.room_avatar_url = room->get_avatar_url();
                     invite.invited_by = invited_by;
                     invite.timestamp = timestamp_json.GetInt64();
                     invite.new_invite = !next_batch.empty();
-- 
cgit v1.2.3-70-g09d2