From b3c8ce3856e48ee325ebcce69dc7d89f4ba78e4b Mon Sep 17 00:00:00 2001
From: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
Date: Thu, 24 May 2018 14:48:52 -0400
Subject: [PATCH] conversationmodel: concurrency issue in placeCall

If the contactAdded signal has a small delay and comes after the
if (isTemporary && (contactIndex = indexOfContact(convId)) < 0)
check from line 538, the call is abruptly stopped without valid
reasons.

In this patch we introduce the same synchronization mechanisms as
af04c34 so that we can handle small delays of contactAdded nicely
and still stop call properly in case of failure while adding contact.

Change-Id: I83b7cd5910d21841b09e969d3baa7b484906941b
Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
---
 src/conversationmodel.cpp | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index cc23613d..899d1cf8 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -533,10 +533,25 @@ ConversationModelPimpl::placeCall(const std::string& uid, bool isAudioOnly)
         url = "ring:" + url; // Add the ring: before or it will fail.
     }
 
-    // If call is with temporary contact, conversation has been removed and must be updated
+    if (isTemporary) {
+        /* Block until we are sure that the final conversation was created by
+           slotContactAdded(). If adding contact failed we should not process
+           any further */
+        std::unique_lock<std::mutex> lock(m_mutex_conversations);
+        auto res = m_condVar_conversation_creation.wait_for(lock, std::chrono::seconds(2), [&]() {
+            return indexOfContact(convId) >= 0;
+        });
+        lock.unlock();
+
+        if (!res) {
+            qDebug() << "ConversationModelPimpl::placeCall reached timeout while waiting for contact to be added. Couldn't place call.";
+            return;
+        }
+    }
+
     int contactIndex;
     if (isTemporary && (contactIndex = indexOfContact(convId)) < 0) {
-        qDebug() << "Can't place call: Other participant is not a contact";
+        qDebug() << "Can't place call: Other participant is not a contact (removed while placing call ?)";
         return;
     }
 
-- 
GitLab