From ad16157b6c7299443a7b2ba919ca463eb08b5647 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Wed, 31 Jan 2024 14:14:51 -0500
Subject: [PATCH] connectionmanager: avoid deadlock on cinfo->mtx_

cinfo->mtx_ MUST be locked before socketsMutex, so it SHOULD never
be locked in a callback. Retrigger the lock in its own thread avoid
a deadlock there.

GitLab: #20
Change-Id: If17af7db81d8ca2b990629446b5d78dc11a785b1
---
 src/connectionmanager.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp
index 37becf7..523d90d 100644
--- a/src/connectionmanager.cpp
+++ b/src/connectionmanager.cpp
@@ -1062,10 +1062,13 @@ ConnectionManager::Impl::sendChannelRequest(const std::weak_ptr<DeviceInfo>& din
         [dinfow, cinfow, wSock = std::weak_ptr(channelSock), name, vid](bool accepted) {
             if (auto dinfo = dinfow.lock()) {
                 dinfo->executePendingOperations(vid, accepted ? wSock.lock() : nullptr, accepted);
-                if (auto cinfo = cinfow.lock()) {
-                    std::lock_guard<std::mutex> lk(cinfo->mutex_);
-                    cinfo->cbIds_.erase(vid);
-                }
+                // Always lock top-down cinfo->mutex
+                dht::ThreadPool::io().run([cinfow, vid]() {
+                    if (auto cinfo = cinfow.lock()) {
+                        std::lock_guard<std::mutex> lk(cinfo->mutex_);
+                        cinfo->cbIds_.erase(vid);
+                    }
+                });
             }
         });
 
-- 
GitLab