From f83f43e25a69a8cb890ec94baa5fa5d6371eac22 Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 17 Aug 2021 10:40:37 +0200 Subject: [PATCH] CoreServices: Move shutdown code into destructor --- src/coreservices.cpp | 252 +++++++++++++++++++++---------------------- src/coreservices.h | 1 - 2 files changed, 124 insertions(+), 129 deletions(-) diff --git a/src/coreservices.cpp b/src/coreservices.cpp index 6e3efe340bde..9e4584caf94c 100644 --- a/src/coreservices.cpp +++ b/src/coreservices.cpp @@ -130,7 +130,130 @@ CoreServices::~CoreServices() { return; } - shutdown(); + Timer t("CoreServices::shutdown"); + t.start(); + + // Stop all pending library operations + qDebug() << t.elapsed(false).debugMillisWithUnit() << "stopping pending Library tasks"; + m_pTrackCollectionManager->stopLibraryScan(); + m_pLibrary->stopPendingTasks(); + + qDebug() << t.elapsed(false).debugMillisWithUnit() << "saving configuration"; + m_pSettingsManager->save(); + + // SoundManager depend on Engine and Config + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting SoundManager"; + CLEAR_AND_CHECK_DELETED(m_pSoundManager); + + // ControllerManager depends on Config + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting ControllerManager"; + CLEAR_AND_CHECK_DELETED(m_pControllerManager); + +#ifdef __VINYLCONTROL__ + // VinylControlManager depends on a CO the engine owns + // (vinylcontrol_enabled in VinylControlControl) + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting VinylControlManager"; + CLEAR_AND_CHECK_DELETED(m_pVCManager); +#endif + + // CoverArtCache is fairly independent of everything else. + CoverArtCache::destroy(); + + // PlayerManager depends on Engine, SoundManager, VinylControlManager, and Config + // The player manager has to be deleted before the library to ensure + // that all modified track metadata of loaded tracks is saved. + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting PlayerManager"; + CLEAR_AND_CHECK_DELETED(m_pPlayerManager); + + // Destroy PlayerInfo explicitly to release the track + // pointers of tracks that were still loaded in decks + // or samplers when PlayerManager was destroyed! + PlayerInfo::destroy(); + + // Delete the library after the view so there are no dangling pointers to + // the data models. + // Depends on RecordingManager and PlayerManager + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting Library"; + CLEAR_AND_CHECK_DELETED(m_pLibrary); + + // RecordingManager depends on config, engine + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting RecordingManager"; + CLEAR_AND_CHECK_DELETED(m_pRecordingManager); + +#ifdef __BROADCAST__ + // BroadcastManager depends on config, engine + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting BroadcastManager"; + CLEAR_AND_CHECK_DELETED(m_pBroadcastManager); +#endif + + // EngineMaster depends on Config and m_pEffectsManager. + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting EngineMaster"; + CLEAR_AND_CHECK_DELETED(m_pEngine); + + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting EffectsManager"; + CLEAR_AND_CHECK_DELETED(m_pEffectsManager); + + // Delete the track collections after all internal track pointers + // in other components have been released by deleting those components + // beforehand! + qDebug() << t.elapsed(false).debugMillisWithUnit() << "detaching all track collections"; + CLEAR_AND_CHECK_DELETED(m_pTrackCollectionManager); + + qDebug() << t.elapsed(false).debugMillisWithUnit() << "closing database connection(s)"; + m_pDbConnectionPool->destroyThreadLocalConnection(); + m_pDbConnectionPool.reset(); // should drop the last reference + + // HACK: Save config again. We saved it once before doing some dangerous + // stuff. We only really want to save it here, but the first one was just + // a precaution. The earlier one can be removed when stuff is more stable + // at exit. + m_pSettingsManager->save(); + + m_pTouchShift.reset(); + + m_pControlIndicatorTimer.reset(); + + // Check for leaked ControlObjects and give warnings. + { + const QList> leakedControls = + ControlDoublePrivate::takeAllInstances(); + if (!leakedControls.isEmpty()) { + qWarning() + << "The following" + << leakedControls.size() + << "controls were leaked:"; + for (auto pCDP : leakedControls) { + ConfigKey key = pCDP->getKey(); + qWarning() << key.group << key.item << pCDP->getCreatorCO(); + // Deleting leaked objects helps to satisfy valgrind. + // These delete calls could cause crashes if a destructor for a control + // we thought was leaked is triggered after this one exits. + // So, only delete so if developer mode is on. + if (CmdlineArgs::Instance().getDeveloper()) { + pCDP->deleteCreatorCO(); + } + } + DEBUG_ASSERT(!"Controls were leaked!"); + } + // Finally drop all shared pointers by exiting this scope + } + + Sandbox::shutdown(); + + qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting SettingsManager"; + m_pSettingsManager.reset(); + + CLEAR_AND_CHECK_DELETED(m_pKeyboardEventFilter); + CLEAR_AND_CHECK_DELETED(m_pKbdConfig); + CLEAR_AND_CHECK_DELETED(m_pKbdConfigEmpty); + + t.elapsed(true); + // Report the total time we have been running. + m_runtime_timer.elapsed(true); + + if (m_cmdlineArgs.getDeveloper()) { + StatsManager::destroy(); + } } void CoreServices::initializeSettings() { @@ -489,131 +612,4 @@ bool CoreServices::initializeDatabase() { return MixxxDb::initDatabaseSchema(dbConnection); } -void CoreServices::shutdown() { - Timer t("CoreServices::shutdown"); - t.start(); - - // Stop all pending library operations - qDebug() << t.elapsed(false).debugMillisWithUnit() << "stopping pending Library tasks"; - m_pTrackCollectionManager->stopLibraryScan(); - m_pLibrary->stopPendingTasks(); - - qDebug() << t.elapsed(false).debugMillisWithUnit() << "saving configuration"; - m_pSettingsManager->save(); - - // SoundManager depend on Engine and Config - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting SoundManager"; - CLEAR_AND_CHECK_DELETED(m_pSoundManager); - - // ControllerManager depends on Config - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting ControllerManager"; - CLEAR_AND_CHECK_DELETED(m_pControllerManager); - -#ifdef __VINYLCONTROL__ - // VinylControlManager depends on a CO the engine owns - // (vinylcontrol_enabled in VinylControlControl) - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting VinylControlManager"; - CLEAR_AND_CHECK_DELETED(m_pVCManager); -#endif - - // CoverArtCache is fairly independent of everything else. - CoverArtCache::destroy(); - - // PlayerManager depends on Engine, SoundManager, VinylControlManager, and Config - // The player manager has to be deleted before the library to ensure - // that all modified track metadata of loaded tracks is saved. - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting PlayerManager"; - CLEAR_AND_CHECK_DELETED(m_pPlayerManager); - - // Destroy PlayerInfo explicitly to release the track - // pointers of tracks that were still loaded in decks - // or samplers when PlayerManager was destroyed! - PlayerInfo::destroy(); - - // Delete the library after the view so there are no dangling pointers to - // the data models. - // Depends on RecordingManager and PlayerManager - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting Library"; - CLEAR_AND_CHECK_DELETED(m_pLibrary); - - // RecordingManager depends on config, engine - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting RecordingManager"; - CLEAR_AND_CHECK_DELETED(m_pRecordingManager); - -#ifdef __BROADCAST__ - // BroadcastManager depends on config, engine - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting BroadcastManager"; - CLEAR_AND_CHECK_DELETED(m_pBroadcastManager); -#endif - - // EngineMaster depends on Config and m_pEffectsManager. - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting EngineMaster"; - CLEAR_AND_CHECK_DELETED(m_pEngine); - - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting EffectsManager"; - CLEAR_AND_CHECK_DELETED(m_pEffectsManager); - - // Delete the track collections after all internal track pointers - // in other components have been released by deleting those components - // beforehand! - qDebug() << t.elapsed(false).debugMillisWithUnit() << "detaching all track collections"; - CLEAR_AND_CHECK_DELETED(m_pTrackCollectionManager); - - qDebug() << t.elapsed(false).debugMillisWithUnit() << "closing database connection(s)"; - m_pDbConnectionPool->destroyThreadLocalConnection(); - m_pDbConnectionPool.reset(); // should drop the last reference - - // HACK: Save config again. We saved it once before doing some dangerous - // stuff. We only really want to save it here, but the first one was just - // a precaution. The earlier one can be removed when stuff is more stable - // at exit. - m_pSettingsManager->save(); - - m_pTouchShift.reset(); - - m_pControlIndicatorTimer.reset(); - - // Check for leaked ControlObjects and give warnings. - { - const QList> leakedControls = - ControlDoublePrivate::takeAllInstances(); - if (!leakedControls.isEmpty()) { - qWarning() - << "The following" - << leakedControls.size() - << "controls were leaked:"; - for (auto pCDP : leakedControls) { - ConfigKey key = pCDP->getKey(); - qWarning() << key.group << key.item << pCDP->getCreatorCO(); - // Deleting leaked objects helps to satisfy valgrind. - // These delete calls could cause crashes if a destructor for a control - // we thought was leaked is triggered after this one exits. - // So, only delete so if developer mode is on. - if (CmdlineArgs::Instance().getDeveloper()) { - pCDP->deleteCreatorCO(); - } - } - DEBUG_ASSERT(!"Controls were leaked!"); - } - // Finally drop all shared pointers by exiting this scope - } - - Sandbox::shutdown(); - - qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting SettingsManager"; - m_pSettingsManager.reset(); - - CLEAR_AND_CHECK_DELETED(m_pKeyboardEventFilter); - CLEAR_AND_CHECK_DELETED(m_pKbdConfig); - CLEAR_AND_CHECK_DELETED(m_pKbdConfigEmpty); - - t.elapsed(true); - // Report the total time we have been running. - m_runtime_timer.elapsed(true); - - if (m_cmdlineArgs.getDeveloper()) { - StatsManager::destroy(); - } -} - } // namespace mixxx diff --git a/src/coreservices.h b/src/coreservices.h index e0dd13597b53..8eeec7156e7d 100644 --- a/src/coreservices.h +++ b/src/coreservices.h @@ -121,7 +121,6 @@ class CoreServices : public QObject { void initializeSettings(); void initializeScreensaverManager(); void initializeLogging(); - void shutdown(); std::shared_ptr m_pSettingsManager; std::shared_ptr m_pControlIndicatorTimer;