Skip to content
Snippets Groups Projects
Commit bebb2c5d authored by Alexandre Lision's avatar Alexandre Lision
Browse files

osx: fix crash on quit

On exit, ContactMethod are destroyed by their QObject parent,
PhoneDirectoryModel instance.

Implemeting a unique_ptr on top of it for m_pDialNumber caused a double free.

First the PhoneDirectoryModel is destroyed, and so all of its children.
Then Calls are destroyed by the CallModel, and the unique_ptr mechanism is
called, but on dealloced ContactMethod.

Issue: #79948
Change-Id: I68fb966d080f4c993ca83c68703d5dfb470f5ad9
parent e62798e7
No related branches found
No related tags found
No related merge requests found
......@@ -746,7 +746,7 @@ ContactMethod* Call::peerContactMethod() const
return d_ptr->m_pPeerContactMethod;
if (d_ptr->m_pDialNumber)
return d_ptr->m_pDialNumber.get();
return d_ptr->m_pDialNumber;
return const_cast<ContactMethod*>(ContactMethod::BLANK());
}
......@@ -1045,7 +1045,7 @@ Media::Media* MediaTypeInference::safeMediaCreator(Call* c, Media::Media::Type t
void Call::setTransferNumber(const QString& number)
{
if (!d_ptr->m_pTransferNumber)
d_ptr->m_pTransferNumber.reset(new TemporaryContactMethod());
d_ptr->m_pTransferNumber = new TemporaryContactMethod();
d_ptr->m_pTransferNumber->setUri(number);
}
......@@ -1225,8 +1225,9 @@ Call::State CallPrivate::stateChanged(const QString& newStateName)
}
if (q_ptr->lifeCycleState() != Call::LifeCycleState::CREATION && m_pDialNumber) {
if (!m_pPeerContactMethod)
m_pPeerContactMethod = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber.get());
m_pDialNumber.reset();
m_pPeerContactMethod = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber);
m_pDialNumber->deleteLater();
m_pDialNumber = nullptr;
}
emit q_ptr->changed();
qDebug() << "Calling stateChanged " << newStateName << " -> " << toDaemonCallState(newStateName) << " on call with state " << previousState << ". Become " << m_CurrentState;
......@@ -1602,8 +1603,10 @@ void CallPrivate::call()
changeCurrentState(Call::State::ABORTED);
if (!m_pDialNumber)
emit q_ptr->dialNumberChanged(QString());
else
m_pDialNumber.reset();
else {
m_pDialNumber->deleteLater();
m_pDialNumber = nullptr;
}
q_ptr->setPeerName(tr("Aborted"));
emit q_ptr->changed();
return;
......@@ -1641,7 +1644,8 @@ void CallPrivate::call()
m_pPeerContactMethod = PhoneDirectoryModel::instance()->getNumber(uri, q_ptr->account());
// m_pDialNumber is now discarded
m_pDialNumber.reset();
m_pDialNumber->deleteLater();
m_pDialNumber = nullptr;
//Refresh peerCM
peerCM = q_ptr->peerContactMethod();
......@@ -1757,8 +1761,9 @@ void CallPrivate::start()
emit q_ptr->changed();
if (m_pDialNumber) {
if (!m_pPeerContactMethod)
m_pPeerContactMethod = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber.get());
m_pDialNumber.reset();
m_pPeerContactMethod = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber);
m_pDialNumber->deleteLater();
m_pDialNumber = nullptr;
}
setStartTimeStamp();
initTimer();
......@@ -1839,12 +1844,12 @@ void Call::appendText(const QString& str)
switch (d_ptr->m_CurrentState) {
case Call::State::TRANSFERRED :
case Call::State::TRANSF_HOLD :
editNumber = d_ptr->m_pTransferNumber.get();
editNumber = d_ptr->m_pTransferNumber;
break;
case Call::State::DIALING :
case Call::State::NEW : {
const bool wasEmpty = (!editNumber) ||editNumber->uri().isEmpty();
editNumber = d_ptr->m_pDialNumber.get();
editNumber = d_ptr->m_pDialNumber;
const bool isEmpty = str.isEmpty();
if (wasEmpty != isEmpty)
......@@ -1889,12 +1894,12 @@ void Call::backspaceItemText()
switch (d_ptr->m_CurrentState) {
case Call::State::TRANSFERRED :
case Call::State::TRANSF_HOLD :
editNumber = d_ptr->m_pTransferNumber.get();
editNumber = d_ptr->m_pTransferNumber;
break;
case Call::State::NEW:
case Call::State::DIALING : {
const bool wasEmpty = (!editNumber) ||editNumber->uri().isEmpty();
editNumber = d_ptr->m_pDialNumber.get();
editNumber = d_ptr->m_pDialNumber;
const bool isEmpty = editNumber->uri().isEmpty();
if (wasEmpty != isEmpty)
......@@ -1942,11 +1947,11 @@ void Call::reset()
switch (d_ptr->m_CurrentState) {
case Call::State::TRANSFERRED :
case Call::State::TRANSF_HOLD :
editNumber = d_ptr->m_pTransferNumber.get();
editNumber = d_ptr->m_pTransferNumber;
break;
case Call::State::DIALING :
case Call::State::NEW :
editNumber = d_ptr->m_pDialNumber.get();
editNumber = d_ptr->m_pDialNumber;
d_ptr->changeCurrentState( Call::State::NEW );
break;
case Call::State::INITIALIZATION :
......
......@@ -48,11 +48,6 @@ namespace Media {
class Recording;
}
// Smart pointer deleter helper
struct DeleteLaterDeleter {
void operator ()(QObject* p) { p->deleteLater(); }
};
class CallPrivate final : public QObject
{
Q_OBJECT
......@@ -274,10 +269,12 @@ private:
//Destructor helper (~Call is private, CallPrivate is a friend class)
static void deleteCall(Call* call);
//!< Used as contact until m_pPeerContactMethod is created
std::unique_ptr<TemporaryContactMethod, DeleteLaterDeleter> m_pDialNumber;
// Used as contact until m_pPeerContactMethod is created
// Owner is PhoneDirectoryModel instance
TemporaryContactMethod* m_pDialNumber;
std::unique_ptr<TemporaryContactMethod> m_pTransferNumber;
// Owner is PhoneDirectoryModel instance
TemporaryContactMethod* m_pTransferNumber;
private Q_SLOTS:
void updated();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment