From d83bcfcf5ca5c4293aecd83607a629c7de16d066 Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
Date: Mon, 13 Apr 2015 17:45:58 -0400
Subject: [PATCH] call: Handle daemon/libringclient IPC race condition

Refs #69138

(cherry picked from commit 19027630ceacdbe542d004b999a2bd790aaab06e)
---
 src/call.cpp                 | 14 ++++++++++++++
 src/callmodel.cpp            | 21 +++++++++++++++++++--
 src/private/accountmodel_p.h |  2 +-
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/call.cpp b/src/call.cpp
index 8d35d0d1..b8a7cff1 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -369,6 +369,13 @@ Call* CallPrivate::buildIncomingCall(const QString& callId)
    const QString from          = details[ CallPrivate::DetailsMapFields::PEER_NUMBER ];
    const QString account       = details[ CallPrivate::DetailsMapFields::ACCOUNT_ID  ];
    const QString peerName      = details[ CallPrivate::DetailsMapFields::PEER_NAME   ];
+
+   //It may be possible that the call has already been invalidated
+   if (account.isEmpty()) {
+      qWarning() << "Building incoming call" << callId << "failed, it may already have been destroyed by the daemon";
+      return nullptr;
+   }
+
    Account*      acc           = AccountModel::instance()->getById(account.toLatin1());
    ContactMethod*  nb          = PhoneDirectoryModel::instance()->getNumber(from,acc);
    Call* call                  = new Call(Call::State::INCOMING, peerName, nb, acc);
@@ -395,6 +402,13 @@ Call* CallPrivate::buildRingingCall(const QString & callId)
    const QString from          = details[ CallPrivate::DetailsMapFields::PEER_NUMBER ];
    const QString account       = details[ CallPrivate::DetailsMapFields::ACCOUNT_ID  ];
    const QString peerName      = details[ CallPrivate::DetailsMapFields::PEER_NAME   ];
+
+   //It may be possible that the call has already been invalidated
+   if (account.isEmpty()) {
+      qWarning() << "Building ringing call" << callId << "failed, it may already have been destroyed by the daemon";
+      return nullptr;
+   }
+
    Account*      acc           = AccountModel::instance()->getById(account.toLatin1());
    ContactMethod*  nb          = PhoneDirectoryModel::instance()->getNumber(from,acc);
    Call* call                  = new Call(Call::State::RINGING, peerName, nb, acc);
diff --git a/src/callmodel.cpp b/src/callmodel.cpp
index c1c79297..1117d9e9 100644
--- a/src/callmodel.cpp
+++ b/src/callmodel.cpp
@@ -443,6 +443,11 @@ Call* CallModel::dialingCall(const QString& peerName, Account* account)
 Call* CallModelPrivate::addIncomingCall(const QString& callId)
 {
    Call* call = addCall2(CallPrivate::buildIncomingCall(callId));
+
+   //The call can already have been invalidated by the daemon, then do nothing
+   if (!call)
+      return nullptr;
+
    //Call without account is not possible
    if (call->account()) {
       if (call->account()->isAutoAnswer()) {
@@ -459,7 +464,12 @@ Call* CallModelPrivate::addIncomingCall(const QString& callId)
 ///Create a ringing call
 Call* CallModelPrivate::addRingingCall(const QString& callId)
 {
-   return addCall2(CallPrivate::buildRingingCall(callId));
+   Call* c = CallPrivate::buildRingingCall(callId);
+
+   if (!c)
+      return nullptr;
+
+   return addCall2(c);
 }
 
 ///Properly remove an internal from the Qt model
@@ -1021,6 +1031,10 @@ void CallModelPrivate::slotCallStateChanged(const QString& callID, const QString
       qDebug() << "Call not found" << callID << "new state" << stateName;
       if(stateName == CallPrivate::StateChange::RINGING) {
          call = addRingingCall(callID);
+
+         if (!call)
+            return;
+
       }
       else {
          qDebug() << "Call doesn't exist in this client. Might have been initialized by another client instance before this one started.";
@@ -1059,7 +1073,10 @@ void CallModelPrivate::slotIncomingCall(const QString& accountID, const QString&
 {
    Q_UNUSED(accountID)
    qDebug() << "Signal : Incoming Call ! ID = " << callID;
-   emit q_ptr->incomingCall(addIncomingCall(callID));
+   Call* c = addIncomingCall(callID);
+
+   if (c)
+      emit q_ptr->incomingCall(c);
 }
 
 ///When a new conference is incoming
diff --git a/src/private/accountmodel_p.h b/src/private/accountmodel_p.h
index dc192b99..a349298a 100644
--- a/src/private/accountmodel_p.h
+++ b/src/private/accountmodel_p.h
@@ -44,7 +44,7 @@ public:
 
    //Helpers
    static Account::RegistrationState fromDaemonName(const QString& st);
-   void enabledProtocol(Account::Protocol proto);
+   void enableProtocol(Account::Protocol proto);
 
    //Attributes
    AccountModel*                     q_ptr                ;
-- 
GitLab