mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-06 20:23:08 +00:00
Fix : Undefined bevaviour on core restart
- Remove useless mutex protection - Remove the constraint on sender events from CoreHandlers. The fact that these events should be on a specific thread is done by the connection. - Fully use the Global State Changed from SDK events and centralized app behaviour to them - Reerite CoreManager initialization to avoid multiple lambda functions and to gain control over threads - Add Start/Stop timer functions for iteration
This commit is contained in:
parent
0685257775
commit
c6c8ed9918
6 changed files with 76 additions and 89 deletions
|
|
@ -397,7 +397,7 @@ void App::initContentApp () {
|
|||
|
||||
QObject::connect(
|
||||
CoreManager::getInstance(),
|
||||
&CoreManager::coreStarted, CoreManager::getInstance(),
|
||||
&CoreManager::managerInitialized, CoreManager::getInstance(),
|
||||
[this, mustBeIconified]() mutable {
|
||||
if(CoreManager::getInstance()->started())
|
||||
openAppAfterInit(mustBeIconified);
|
||||
|
|
@ -894,7 +894,7 @@ void App::openAppAfterInit (bool mustBeIconified) {
|
|||
coreManager->getCallsListModel()->launchAudioCall(sipAddress);
|
||||
}else{
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(CoreManager::getInstance(), &CoreManager::coreStarted,context,
|
||||
QObject::connect(CoreManager::getInstance(), &CoreManager::managerInitialized,context,
|
||||
[sipAddress,coreManager, context]() mutable {
|
||||
if(context){
|
||||
delete context;
|
||||
|
|
|
|||
|
|
@ -50,36 +50,13 @@ void scheduleFunctionInApp (function<void()> func) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
CoreHandlers::CoreHandlers (CoreManager *coreManager) {
|
||||
mCoreStartedLock = new QMutex();
|
||||
QObject::connect(coreManager, &CoreManager::coreCreated, this, &CoreHandlers::handleCoreCreated);
|
||||
Q_UNUSED(coreManager)
|
||||
}
|
||||
|
||||
CoreHandlers::~CoreHandlers () {
|
||||
delete mCoreStartedLock;
|
||||
mCoreStartedLock = nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CoreHandlers::handleCoreCreated () {
|
||||
mCoreStartedLock->lock();
|
||||
|
||||
Q_ASSERT(mCoreCreated == false);
|
||||
mCoreCreated = true;
|
||||
notifyCoreStarted();
|
||||
mCoreStartedLock->unlock();
|
||||
}
|
||||
|
||||
void CoreHandlers::notifyCoreStarted () {
|
||||
if (mCoreCreated && mCoreStarted)
|
||||
scheduleFunctionInApp([this] {
|
||||
qInfo() << QStringLiteral("Core started.");
|
||||
emit coreStarted();
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CoreHandlers::onAuthenticationRequested (
|
||||
const shared_ptr<linphone::Core> & core,
|
||||
const shared_ptr<linphone::AuthInfo> &authInfo,
|
||||
|
|
@ -136,22 +113,23 @@ void CoreHandlers::onDtmfReceived(
|
|||
const std::shared_ptr<linphone::Core> & lc,
|
||||
const std::shared_ptr<linphone::Call> & call,
|
||||
int dtmf) {
|
||||
Q_UNUSED(lc)
|
||||
Q_UNUSED(call)
|
||||
CoreManager::getInstance()->getCore()->playDtmf((char)dtmf, CallModel::DtmfSoundDelay);
|
||||
}
|
||||
void CoreHandlers::onGlobalStateChanged (
|
||||
const shared_ptr<linphone::Core> &,
|
||||
const shared_ptr<linphone::Core> &core,
|
||||
linphone::GlobalState gstate,
|
||||
const string &
|
||||
const string & message
|
||||
) {
|
||||
if (gstate == linphone::GlobalState::On) {
|
||||
mCoreStartedLock->lock();
|
||||
|
||||
Q_ASSERT(mCoreStarted == false);
|
||||
mCoreStarted = true;
|
||||
notifyCoreStarted();
|
||||
|
||||
mCoreStartedLock->unlock();
|
||||
}
|
||||
Q_UNUSED(core)
|
||||
Q_UNUSED(message)
|
||||
if( gstate == linphone::GlobalState::On)
|
||||
emit coreStarted();
|
||||
else if( gstate == linphone::GlobalState::Off)
|
||||
emit coreStopped();
|
||||
else if( gstate == linphone::GlobalState::Startup)
|
||||
emit coreStarting();
|
||||
}
|
||||
|
||||
void CoreHandlers::onIsComposingReceived (
|
||||
|
|
@ -256,6 +234,7 @@ void CoreHandlers::onTransferStateChanged (
|
|||
case linphone::Call::State::Paused:
|
||||
case linphone::Call::State::PausedByRemote:
|
||||
case linphone::Call::State::Pausing:
|
||||
case linphone::Call::State::PushIncomingReceived:
|
||||
case linphone::Call::State::Referred:
|
||||
case linphone::Call::State::Released:
|
||||
case linphone::Call::State::Resuming:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ signals:
|
|||
void callTransferFailed (const std::shared_ptr<linphone::Call> &call);
|
||||
void callTransferSucceeded (const std::shared_ptr<linphone::Call> &call);
|
||||
void callCreated(const std::shared_ptr<linphone::Call> & call);
|
||||
void coreStarting();
|
||||
void coreStarted ();
|
||||
void coreStopped ();
|
||||
void isComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
||||
void logsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info);
|
||||
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||
|
|
@ -54,8 +56,6 @@ signals:
|
|||
void ecCalibrationResult(linphone::EcCalibratorStatus status, int delayMs);
|
||||
|
||||
private:
|
||||
void handleCoreCreated ();
|
||||
void notifyCoreStarted ();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Linphone callbacks.
|
||||
|
|
@ -165,11 +165,6 @@ private:
|
|||
) override;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool mCoreCreated = false;
|
||||
bool mCoreStarted = false;
|
||||
|
||||
QMutex *mCoreStartedLock = nullptr;
|
||||
};
|
||||
|
||||
#endif // CORE_HANDLERS_H_
|
||||
|
|
|
|||
|
|
@ -72,43 +72,39 @@ CoreManager *CoreManager::mInstance;
|
|||
|
||||
CoreManager::CoreManager (QObject *parent, const QString &configPath) :
|
||||
QObject(parent), mHandlers(make_shared<CoreHandlers>(this)) {
|
||||
QTimer * delayedCreationTimer = new QTimer();
|
||||
delayedCreationTimer->setSingleShot(true);
|
||||
QObject::connect(delayedCreationTimer, &QTimer::timeout, this , [configPath, this, delayedCreationTimer]{
|
||||
delayedCreationTimer->deleteLater();
|
||||
createLinphoneCore(configPath);
|
||||
qInfo() << QStringLiteral("Core created. Enable iterate.");
|
||||
mInstance->mCbsTimer->start();
|
||||
std::shared_ptr<CoreHandlers> h = mInstance->getHandlers();// Protect handler as we will enter its function where it can be deleted (like while restarting)
|
||||
emit mInstance->coreCreated();
|
||||
});
|
||||
|
||||
mCore = nullptr;
|
||||
CoreHandlers *coreHandlers = mHandlers.get();
|
||||
|
||||
QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, [] {
|
||||
// Do not change this order. :) (Or pray.)
|
||||
mInstance->mCallsListModel = new CallsListModel(mInstance);
|
||||
mInstance->mContactsListModel = new ContactsListModel(mInstance);
|
||||
mInstance->mAccountSettingsModel = new AccountSettingsModel(mInstance);
|
||||
mInstance->mSettingsModel = new SettingsModel(mInstance);
|
||||
mInstance->mSipAddressesModel = new SipAddressesModel(mInstance);
|
||||
EventCountNotifier *eventCountNotifier = new EventCountNotifier(mInstance);
|
||||
eventCountNotifier->updateUnreadMessageCount();
|
||||
QObject::connect(eventCountNotifier, &EventCountNotifier::eventCountChanged,
|
||||
mInstance, &CoreManager::eventCountChanged
|
||||
);
|
||||
mInstance->mEventCountNotifier = eventCountNotifier;
|
||||
mInstance->migrate();
|
||||
mInstance->mStarted = true;
|
||||
emit mInstance->coreStarted();
|
||||
});
|
||||
|
||||
QObject::connect(coreHandlers, &CoreHandlers::coreStarting, this, &CoreManager::startIterate, Qt::QueuedConnection);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, &CoreManager::initManager, Qt::QueuedConnection);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::coreStopped, this, &CoreManager::stopIterate, Qt::QueuedConnection);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::logsUploadStateChanged, this, &CoreManager::handleLogsUploadStateChanged);
|
||||
delayedCreationTimer->start(CbsCallInterval);
|
||||
|
||||
createLinphoneCore(configPath);
|
||||
}
|
||||
|
||||
CoreManager::~CoreManager(){
|
||||
mCore->removeListener(mHandlers);
|
||||
mHandlers = nullptr;// Call destructor
|
||||
mCore = nullptr;// Call destructor
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CoreManager::initManager(){
|
||||
mCallsListModel = new CallsListModel(this);
|
||||
mContactsListModel = new ContactsListModel(this);
|
||||
mAccountSettingsModel = new AccountSettingsModel(this);
|
||||
mSettingsModel = new SettingsModel(this);
|
||||
mSipAddressesModel = new SipAddressesModel(this);
|
||||
mEventCountNotifier = new EventCountNotifier(this);
|
||||
mEventCountNotifier->updateUnreadMessageCount();
|
||||
QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged);
|
||||
migrate();
|
||||
mStarted = true;
|
||||
qInfo() << QStringLiteral("Core created. Enable iterate.");
|
||||
emit managerInitialized();
|
||||
}
|
||||
|
||||
shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, const QString &localAddress) {
|
||||
if (peerAddress.isEmpty() || localAddress.isEmpty())
|
||||
return nullptr;
|
||||
|
|
@ -161,13 +157,7 @@ HistoryModel* CoreManager::getHistoryModel(){
|
|||
void CoreManager::init (QObject *parent, const QString &configPath) {
|
||||
if (mInstance)
|
||||
return;
|
||||
|
||||
mInstance = new CoreManager(parent, configPath);
|
||||
|
||||
QTimer *timer = mInstance->mCbsTimer = new QTimer(mInstance);
|
||||
timer->setInterval(CbsCallInterval);
|
||||
|
||||
QObject::connect(timer, &QTimer::timeout, mInstance, &CoreManager::iterate);
|
||||
}
|
||||
|
||||
void CoreManager::uninit () {
|
||||
|
|
@ -176,8 +166,11 @@ void CoreManager::uninit () {
|
|||
mInstance = nullptr;
|
||||
qInfo() << "Linphone Core is destroyed";
|
||||
});
|
||||
mInstance->mCbsTimer->stop();
|
||||
mInstance->deleteLater();// Ensure to take time to delete the instance
|
||||
QObject::connect(mInstance->getHandlers().get(), &CoreHandlers::coreStopped, mInstance, &QObject::deleteLater);
|
||||
|
||||
mInstance->lockVideoRender();// Stop do iterations. We have to protect GUI.
|
||||
mInstance->mCore->stop();
|
||||
mInstance->unlockVideoRender();
|
||||
QTest::qWaitFor([&]() {return mInstance == nullptr;},10000);
|
||||
if( mInstance){
|
||||
qWarning() << "Linphone Core couldn't destroy in time. It may lead to have multiple session of Linphone Core";
|
||||
|
|
@ -338,12 +331,27 @@ int CoreManager::getMissedCallCount(const QString &peerAddress, const QString &l
|
|||
int CoreManager::getMissedCallCountFromLocal( const QString &localAddress)const{
|
||||
return mEventCountNotifier ? mEventCountNotifier->getMissedCallCountFromLocal(localAddress) : 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CoreManager::startIterate(){
|
||||
mCbsTimer = new QTimer(this);
|
||||
mCbsTimer->setInterval(CbsCallInterval);
|
||||
QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate);
|
||||
mCbsTimer->start();
|
||||
}
|
||||
|
||||
void CoreManager::stopIterate(){
|
||||
mCbsTimer->stop();
|
||||
mCbsTimer->deleteLater();// allow the timer to continue its stuff
|
||||
mCbsTimer = nullptr;
|
||||
}
|
||||
|
||||
void CoreManager::iterate () {
|
||||
mInstance->lockVideoRender();
|
||||
mCore->iterate();
|
||||
mInstance->unlockVideoRender();
|
||||
lockVideoRender();
|
||||
if(mCore)
|
||||
mCore->iterate();
|
||||
unlockVideoRender();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -137,9 +137,13 @@ public:
|
|||
|
||||
static bool isInstanciated(){return mInstance!=nullptr;}
|
||||
|
||||
public slots:
|
||||
void initManager();
|
||||
void startIterate();
|
||||
void stopIterate();
|
||||
|
||||
signals:
|
||||
void coreCreated ();
|
||||
void coreStarted ();
|
||||
void managerInitialized ();
|
||||
|
||||
void chatModelCreated (const std::shared_ptr<ChatModel> &chatModel);
|
||||
void historyModelCreated (HistoryModel *historyModel);
|
||||
|
|
@ -150,6 +154,7 @@ signals:
|
|||
|
||||
private:
|
||||
CoreManager (QObject *parent, const QString &configPath);
|
||||
~CoreManager ();
|
||||
|
||||
void setDatabasesPaths ();
|
||||
void setOtherPaths ();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ ApplicationWindow {
|
|||
|
||||
Connections {
|
||||
target: CoreManager
|
||||
onCoreStarted: mainLoader.active = true
|
||||
onManagerInitialized: mainLoader.active = true
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue