From fd2f2815448ce4072dcbc3995950788573d63f3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Fri, 24 May 2024 10:03:40 -0400
Subject: [PATCH] conversation_module: avoid deadlock on member change

Conversation::pull lock writeMtx_ while announcing new commits.
If a member changes occurs, this can lock conv->mtx and
other operations can wait on writeMtx_ too.

GitLab: #994
Change-Id: I605ba6d4acb7b25a591be86bf37e9d549eeba8c0
---
 src/jamidht/conversation_module.cpp | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp
index db16c086d1..75044ef201 100644
--- a/src/jamidht/conversation_module.cpp
+++ b/src/jamidht/conversation_module.cpp
@@ -743,8 +743,12 @@ ConversationModule::Impl::handlePendingConversation(const std::string& conversat
     };
     try {
         auto conversation = std::make_shared<Conversation>(acc, deviceId, conversationId);
-        conversation->onMembersChanged([this, conversationId](const auto& members) {
-            setConversationMembers(conversationId, members);
+        conversation->onMembersChanged([w=weak_from_this(), conversationId](const auto& members) {
+            // Delay in another thread to avoid deadlocks
+            dht::ThreadPool::io().run([w, conversationId, members = std::move(members)] {
+                if (auto sthis = w.lock())
+                    sthis->setConversationMembers(conversationId, members);
+            });
         });
         conversation->onMessageStatusChanged([this, conversationId](const auto& status) {
             auto msg = std::make_shared<SyncMsg>();
@@ -1550,8 +1554,11 @@ ConversationModule::loadConversations()
                 });
                 conv->onMembersChanged(
                     [w = pimpl_->weak_from_this(), repository](const auto& members) {
-                        if (auto p = w.lock())
-                            p->setConversationMembers(repository, members);
+                        // Delay in another thread to avoid deadlocks
+                        dht::ThreadPool::io().run([w, repository, members = std::move(members)] {
+                            if (auto sthis = w.lock())
+                                sthis->setConversationMembers(repository, members);
+                        });
                     });
                 conv->onNeedSocket(pimpl_->onNeedSwarmSocket_);
                 auto members = conv->memberUris(acc->getUsername(), {});
@@ -2022,8 +2029,12 @@ ConversationModule::startConversation(ConversationMode mode, const std::string&
             msg->ms = {{conversationId, status}};
             pimpl_->needsSyncingCb_(std::move(msg));
         });
-        conversation->onMembersChanged([this, conversationId](const auto& members) {
-            pimpl_->setConversationMembers(conversationId, members);
+        conversation->onMembersChanged([w=pimpl_->weak_from_this(), conversationId](const auto& members) {
+            // Delay in another thread to avoid deadlocks
+            dht::ThreadPool::io().run([w, conversationId, members = std::move(members)] {
+                if (auto sthis = w.lock())
+                    sthis->setConversationMembers(conversationId, members);
+            });
         });
         conversation->onNeedSocket(pimpl_->onNeedSwarmSocket_);
 #ifdef LIBJAMI_TESTABLE
-- 
GitLab