From 3243334bfad42a8d3fc83d40556f39abeecad57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Thu, 13 Jul 2023 11:43:25 -0400 Subject: [PATCH] conversation: use same lock for active/hosted calls and avoid deadlock while announcing ended calls because convModule() is already locked Change-Id: I3430afc6aa8cafba151a52313c3904cdfd9013fe --- src/jamidht/conversation.cpp | 52 +++++++++++++---------------- src/jamidht/conversation.h | 2 +- src/jamidht/conversation_module.cpp | 2 +- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/jamidht/conversation.cpp b/src/jamidht/conversation.cpp index 5f5a9b0c16..f8ce212dc7 100644 --- a/src/jamidht/conversation.cpp +++ b/src/jamidht/conversation.cpp @@ -216,13 +216,6 @@ public: } mutable std::string fmtStr_; - /** - * If, for whatever reason, the daemon is stopped while hosting a conference, - * we need to announce the end of this call when restarting. - * To avoid to keep active calls forever. - */ - std::vector<std::string> announceEndedCalls(); - ~Impl() { try { @@ -233,7 +226,12 @@ public: } } - std::vector<std::string> refreshActiveCalls(); + /** + * If, for whatever reason, the daemon is stopped while hosting a conference, + * we need to announce the end of this call when restarting. + * To avoid to keep active calls forever. + */ + std::vector<std::string> commitsEndedCalls(); bool isAdmin() const; std::string repoPath() const; @@ -536,7 +534,7 @@ public: auto file = fileutils::loadFile(hostedCallsPath_); // load values msgpack::object_handle oh = msgpack::unpack((const char*) file.data(), file.size()); - std::lock_guard<std::mutex> lk {hostedCallsMtx_}; + std::lock_guard<std::mutex> lk {activeCallsMtx_}; oh.get().convert(hostedCalls_); } catch (const std::exception& e) { return; @@ -629,7 +627,6 @@ public: // Manage hosted calls on this device std::string hostedCallsPath_ {}; - mutable std::mutex hostedCallsMtx_ {}; mutable std::map<std::string, uint64_t /* start time */> hostedCalls_ {}; // Manage active calls for this conversation (can be hosted by other devices) std::string activeCallsPath_ {}; @@ -687,15 +684,7 @@ Conversation::Impl::getMembers(bool includeInvited, bool includeLeft, bool inclu } std::vector<std::string> -Conversation::Impl::refreshActiveCalls() -{ - loadActiveCalls(); - loadHostedCalls(); - return announceEndedCalls(); -} - -std::vector<std::string> -Conversation::Impl::announceEndedCalls() +Conversation::Impl::commitsEndedCalls() { auto shared = account_.lock(); // Handle current calls @@ -733,11 +722,6 @@ Conversation::Impl::announceEndedCalls() hostedCalls_.clear(); saveActiveCalls(); saveHostedCalls(); - lkA.unlock(); - lk.unlock(); - if (!commits.empty()) { - announce(commits); - } return commits; } @@ -1915,9 +1899,19 @@ Conversation::bootstrap(std::function<void()> onBootstraped, const std::vector<D } std::vector<std::string> -Conversation::refreshActiveCalls() +Conversation::commitsEndedCalls() { - return pimpl_->refreshActiveCalls(); + pimpl_->loadActiveCalls(); + pimpl_->loadHostedCalls(); + auto commits = pimpl_->commitsEndedCalls(); + if (!commits.empty()) { + // Announce to client + dht::ThreadPool::io().run([w = weak(), commits]{ + if (auto sthis = w.lock()) + sthis->pimpl_->announce(commits); + }); + } + return commits; } void @@ -1997,7 +1991,7 @@ Conversation::hostConference(Json::Value&& message, OnDoneCb&& cb) auto now = std::chrono::system_clock::now(); auto nowSecs = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); { - std::lock_guard<std::mutex> lk(pimpl_->hostedCallsMtx_); + std::lock_guard<std::mutex> lk(pimpl_->activeCallsMtx_); pimpl_->hostedCalls_[message["confId"].asString()] = nowSecs; pimpl_->saveHostedCalls(); } @@ -2014,7 +2008,7 @@ Conversation::isHosting(const std::string& confId) const auto info = infos(); if (info["rdvDevice"] == shared->currentDeviceId() && info["rdvHost"] == shared->getUsername()) return true; // We are the current device Host - std::lock_guard<std::mutex> lk(pimpl_->hostedCallsMtx_); + std::lock_guard<std::mutex> lk(pimpl_->activeCallsMtx_); return pimpl_->hostedCalls_.find(confId) != pimpl_->hostedCalls_.end(); } @@ -2028,7 +2022,7 @@ Conversation::removeActiveConference(Json::Value&& message, OnDoneCb&& cb) auto erased = false; { - std::lock_guard<std::mutex> lk(pimpl_->hostedCallsMtx_); + std::lock_guard<std::mutex> lk(pimpl_->activeCallsMtx_); erased = pimpl_->hostedCalls_.erase(message["confId"].asString()); } if (erased) { diff --git a/src/jamidht/conversation.h b/src/jamidht/conversation.h index 96d778ea88..387d18b1ad 100644 --- a/src/jamidht/conversation.h +++ b/src/jamidht/conversation.h @@ -171,7 +171,7 @@ public: * and commit all the crashed calls * @return Commits added */ - std::vector<std::string> refreshActiveCalls(); + std::vector<std::string> commitsEndedCalls(); /** * Add a callback to update upper layers diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index 8919f1831d..73efdc0fb1 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -1184,7 +1184,7 @@ ConversationModule::loadConversations() conv->setRemovingFlag(); toRm.insert(repository); } - auto commits = conv->refreshActiveCalls(); + auto commits = conv->commitsEndedCalls(); if (!commits.empty()) { // Note: here, this means that some calls were actives while the // daemon finished (can be a crash). -- GitLab