From 4b68da458f6058d979b60d0a87438da123cf25b1 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 11 Mar 2023 19:46:23 +0300 Subject: [PATCH] debugged a crash, keys are now fetching, refactored main, added some exceptions instead of ints, debugged termination process --- core/delayManager/job.h | 6 ++ core/delayManager/manager.cpp | 103 ++++++++++++++++---- core/delayManager/manager.h | 21 +++++ core/handlers/trusthandler.cpp | 4 +- external/qxmpp | 2 +- external/storage | 2 +- main/main.cpp | 104 +------------------- main/root.cpp | 167 +++++++++++++++++++++++++++++++-- main/root.h | 42 +++++++++ 9 files changed, 321 insertions(+), 130 deletions(-) diff --git a/core/delayManager/job.h b/core/delayManager/job.h index 633f2b2..6bfdc1d 100644 --- a/core/delayManager/job.h +++ b/core/delayManager/job.h @@ -32,6 +32,12 @@ public: infoForUser, ownInfoForUser }; + inline static constexpr const char * const TypeString[] = { + "cardInternal", + "ownCardInternal", + "infoForUser", + "ownInfoForUser" + }; protected: Job(Id id, Type type); Job(const Job& other); diff --git a/core/delayManager/manager.cpp b/core/delayManager/manager.cpp index 6a15544..3281bc6 100644 --- a/core/delayManager/manager.cpp +++ b/core/delayManager/manager.cpp @@ -67,8 +67,13 @@ void Core::DelayManager::Manager::getInfo(const QString& jid) { Job* job = nullptr; #ifdef WITH_OMEMO std::map::const_iterator bitr = requestedBundles.find(jid); - if (bitr != requestedBundles.end()) - job = runningJobs.at(bitr->second); + if (bitr != requestedBundles.end()) { + std::map::const_iterator itr = runningJobs.find(bitr->second); + if (itr == runningJobs.end()) + throw JobNotFound(bitr->second); + + job = itr->second; + } else #endif job = getVCardJob(jid); @@ -109,10 +114,19 @@ Core::DelayManager::Job* Core::DelayManager::Manager::getVCardJob(const QString& std::map::const_iterator sitr = scheduledVCards.find(jid); if (sitr == scheduledVCards.end()) { std::map::const_iterator ritr = requestedVCards.find(jid); - if (ritr != requestedVCards.end()) - job = runningJobs.at(ritr->second); + if (ritr != requestedVCards.end()) { + std::map::const_iterator itr = runningJobs.find(ritr->second); + if (itr == runningJobs.end()) + throw JobNotFound(ritr->second, "getVCardJob:1"); + + job = itr->second; + } } else { - job = *(scheduledJobsById.find(sitr->second)); + StorageById::const_iterator itr = scheduledJobsById.find(sitr->second); + if (itr == scheduledJobsById.end()) + throw JobNotFound(sitr->second, "getVCardJob:2"); + + job = *itr; } return job; @@ -177,7 +191,7 @@ void Core::DelayManager::Manager::executeJob(Job* job) { void Core::DelayManager::Manager::jobIsDone(Job::Id jobId) { std::map::const_iterator itr = runningJobs.find(jobId); if (itr == runningJobs.end()) { - throw 8573; //not supposed to happen, ever + throw JobNotFound(jobId, "jobIsDone"); } Job* job = itr->second; delete job; @@ -201,9 +215,8 @@ void Core::DelayManager::Manager::replaceJob(Job* job) { if (sitr != scheduledJobsById.end()) { delete *(sitr); scheduledJobsById.replace(sitr, job); - } else { - throw 8574; //not supposed to happen, ever - } + } else + throw JobNotFound(job->id, "replaceJob"); } } @@ -278,7 +291,12 @@ void Core::DelayManager::Manager::receivedVCard(const QString& jid, const Shared } Job::Id jobId = cardItr->second; requestedVCards.erase(cardItr); - Job* job = runningJobs.at(jobId); + std::map::const_iterator itr = runningJobs.find(jobId); + if (itr == runningJobs.end()) { + throw JobNotFound(jobId, "receivedVCard"); + } + Job* job = itr->second; + switch (job->type) { case Job::Type::cardInternal: jobIsDone(jobId); @@ -300,14 +318,22 @@ void Core::DelayManager::Manager::receivedVCard(const QString& jid, const Shared } break; default: - throw 8576; + throw UnexpectedJobType(job->type, "receivedVCard"); } } void Core::DelayManager::Manager::receivedOwnVCard(const Shared::VCard& card) { + if (ownVCardJobId == 0) { + qDebug() << "received own VCard for" << ownJid << "but it was never requested through manager, ignoring"; + return; + } Job::Id jobId = ownVCardJobId; ownVCardJobId = 0; - Job* job = runningJobs.at(jobId); + std::map::const_iterator itr = runningJobs.find(jobId); + if (itr == runningJobs.end()) { + throw JobNotFound(jobId, "receivedOwnVCard"); + } + Job* job = itr->second; switch (job->type) { case Job::Type::ownCardInternal: jobIsDone(jobId); @@ -328,19 +354,24 @@ void Core::DelayManager::Manager::receivedOwnVCard(const Shared::VCard& card) { } break; default: - throw 8576; + throw UnexpectedJobType(job->type, "receivedVCard"); } } void Core::DelayManager::Manager::receivedBundles(const QString& jid, const std::list& keys) { std::map::const_iterator itr = requestedBundles.find(jid); if (itr == requestedBundles.end()) { - throw 8577; //never supposed to happen, the state is not correct; + qDebug() << "received bundles for" << jid << "but they were never requested through manager, ignoring"; + return; } Job::Id jobId = itr->second; requestedBundles.erase(itr); - Job* jb = runningJobs.at(jobId); + std::map::const_iterator jitr = runningJobs.find(jobId); + if (jitr == runningJobs.end()) { + throw JobNotFound(jobId, "receivedBundles"); + } + Job* jb = jitr->second; InfoForUser* job = dynamic_cast(jb); Shared::Info info(jid); @@ -350,9 +381,17 @@ void Core::DelayManager::Manager::receivedBundles(const QString& jid, const std: } void Core::DelayManager::Manager::receivedOwnBundles(const std::list& keys) { + if (ownInfoJobId == 0) { + qDebug() << "received own bundles for" << ownJid << "but they were never requested through manager, ignoring"; + return; + } Job::Id jobId = ownInfoJobId; ownInfoJobId = 0; - Job* jb = runningJobs.at(jobId); + std::map::const_iterator jitr = runningJobs.find(jobId); + if (jitr == runningJobs.end()) { + throw JobNotFound(jobId, "receivedOwnBundles"); + } + Job* jb = jitr->second; OwnInfoForUser* job = dynamic_cast(jb); Shared::Info info(ownJid); @@ -364,3 +403,35 @@ void Core::DelayManager::Manager::receivedOwnBundles(const std::list(type)]; + if (method.size() > 0) { + msg += " in method " + method; + } + return msg; +} + +Core::DelayManager::Manager::JobNotFound::JobNotFound(Job::Id p_id, const std::string& p_method) : + Exception(), + id(p_id), + method(p_method) +{} + +std::string Core::DelayManager::Manager::JobNotFound::getMessage() const { + std::string msg("Job with id "); + msg += std::to_string(id); + msg += " was not found"; + if (method.size() > 0) { + msg += " in method " + method; + } + return msg; +} diff --git a/core/delayManager/manager.h b/core/delayManager/manager.h index 61920ec..127d25a 100644 --- a/core/delayManager/manager.h +++ b/core/delayManager/manager.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include +#include #include "job.h" @@ -121,6 +123,25 @@ private: std::map requestedBundles; #endif QString ownJid; + +public: + class UnexpectedJobType: public Utils::Exception { + public: + UnexpectedJobType(Job::Type p_type, const std::string& p_method = ""); + std::string getMessage() const override; + private: + Job::Type type; + std::string method; + }; + + class JobNotFound: public Utils::Exception { + public: + JobNotFound(Job::Id p_id, const std::string& p_method = ""); + std::string getMessage() const override; + private: + Job::Id id; + std::string method; + }; }; } diff --git a/core/handlers/trusthandler.cpp b/core/handlers/trusthandler.cpp index eb75219..647d568 100644 --- a/core/handlers/trusthandler.cpp +++ b/core/handlers/trusthandler.cpp @@ -93,7 +93,9 @@ QXmppTask Core::TrustHandler::trustLevel( Shared::TrustLevel level = Shared::TrustLevel::undecided; try { Keys map = cache->getRecord(keyOwnerJid); - level = map.at(keyId); + Keys::const_iterator itr = map.find(keyId); + if (itr != map.end()) + level = itr->second; } catch (const DataBase::NotFound& e) {} return Core::makeReadyTask(std::move(convert(level))); } diff --git a/external/qxmpp b/external/qxmpp index 9d57624..d679ad1 160000 --- a/external/qxmpp +++ b/external/qxmpp @@ -1 +1 @@ -Subproject commit 9d5762499fbddb3dd1ed8eeca16f9db70adc27d0 +Subproject commit d679ad1c49eeb28be2ac3a75bd7fd1a9be24d483 diff --git a/external/storage b/external/storage index a79dae8..6a8f67a 160000 --- a/external/storage +++ b/external/storage @@ -1 +1 @@ -Subproject commit a79dae8fd07b36446041f6f85e2ad42cf5ae5264 +Subproject commit 6a8f67ac34de286588cd89e3218f55b54da47f42 diff --git a/main/main.cpp b/main/main.cpp index 5a7e034..afe1cf2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -17,22 +17,11 @@ */ #include "root.h" -#include "shared/global.h" #include "shared/messageinfo.h" -#include "shared/pathcheck.h" #include "shared/identity.h" #include "shared/info.h" -#include "main/application.h" -#include "core/signalcatcher.h" -#include "core/squawk.h" -#include -#include -#include -#include -#include -#include -#include +#include #ifdef WITH_OMEMO #include @@ -60,97 +49,10 @@ int main(int argc, char *argv[]) #endif Root app(argc, argv); - SignalCatcher sc(&app); - - Root::setApplicationName("squawk"); - Root::setOrganizationName("macaw.me"); - Root::setApplicationDisplayName("Squawk"); - Root::setApplicationVersion("0.2.3"); - app.setDesktopFileName("squawk"); - - QTranslator qtTranslator; - qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - app.installTranslator(&qtTranslator); - - QTranslator myappTranslator; - QStringList shares = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); - bool found = false; - for (QString share : shares) { - found = myappTranslator.load(QLocale(), QLatin1String("squawk"), ".", share + "/l10n"); - if (found) { - break; - } - } - if (!found) { - myappTranslator.load(QLocale(), QLatin1String("squawk"), ".", QCoreApplication::applicationDirPath()); - } - - app.installTranslator(&myappTranslator); - - QIcon icon; - icon.addFile(":images/logo.svg", QSize(16, 16)); - icon.addFile(":images/logo.svg", QSize(24, 24)); - icon.addFile(":images/logo.svg", QSize(32, 32)); - icon.addFile(":images/logo.svg", QSize(48, 48)); - icon.addFile(":images/logo.svg", QSize(64, 64)); - icon.addFile(":images/logo.svg", QSize(96, 96)); - icon.addFile(":images/logo.svg", QSize(128, 128)); - icon.addFile(":images/logo.svg", QSize(256, 256)); - icon.addFile(":images/logo.svg", QSize(512, 512)); - Root::setWindowIcon(icon); - - new Shared::Global(); //translates enums - - QSettings settings; - QVariant vs = settings.value("style"); - if (vs.isValid()) { - QString style = vs.toString().toLower(); - if (style != "system") { - Shared::Global::setStyle(style); - } - } - if (Shared::Global::supported("colorSchemeTools")) { - QVariant vt = settings.value("theme"); - if (vt.isValid()) { - QString theme = vt.toString(); - if (theme.toLower() != "system") { - Shared::Global::setTheme(theme); - } - } - } - QString path = Shared::downloadsPathCheck(); - if (path.size() > 0) { - settings.setValue("downloadsPath", path); - } else { - qDebug() << "couldn't initialize directory for downloads, quitting"; + if (!app.initializeSettings()) return -1; - } - - Core::Squawk* squawk = new Core::Squawk(); - QThread* coreThread = new QThread(); - squawk->moveToThread(coreThread); - - Application application(squawk); - QObject::connect(&sc, &SignalCatcher::interrupt, &application, &Application::quit); - - QObject::connect(coreThread, &QThread::started, squawk, &Core::Squawk::start); - QObject::connect(&application, &Application::quitting, squawk, &Core::Squawk::stop); - //QObject::connect(&app, &QApplication::aboutToQuit, &w, &QMainWindow::close); - QObject::connect(squawk, &Core::Squawk::quit, squawk, &Core::Squawk::deleteLater); - QObject::connect(squawk, &Core::Squawk::destroyed, coreThread, &QThread::quit, Qt::QueuedConnection); - QObject::connect(coreThread, &QThread::finished, &app, &Root::quit, Qt::QueuedConnection); - coreThread->start(); - int result = app.exec(); - - if (coreThread->isRunning()) { - //coreThread->wait(); - //todo if I uncomment that, the app will not quit if it has reconnected at least once - //it feels like a symptom of something badly desinged in the core thread - //need to investigate; - } - - return result; + return app.run(); } diff --git a/main/root.cpp b/main/root.cpp index 96b37b9..d43ae2f 100644 --- a/main/root.cpp +++ b/main/root.cpp @@ -17,27 +17,174 @@ #include "root.h" #include #include +#include +#include + +#include + +#include + +const std::vector Root::appIconSizes({ + 16, 24, 32, 48, 64, 96, 128, 256, 512 +}); Root::Root(int& argc, char *argv[]) : - QApplication(argc, argv) - {} + QApplication(argc, argv), + signalCatcher(this), + defaultTranslator(), + currentTranslator(), + appIcon(), + settings(), + componentsInitialized(false), + global(nullptr), + coreThread(nullptr), + core(nullptr), + gui(nullptr) +{ + setApplicationName("squawk"); + setOrganizationName("macaw.me"); + setApplicationDisplayName("Squawk"); + setApplicationVersion("0.2.3"); + setDesktopFileName("squawk"); + + initializeTranslation(); + initializeAppIcon(); + + global = new Shared::Global(); //important to instantiate after initialization of translations; +} + +Root::~Root() { + if (componentsInitialized) { + delete gui; + if (core != nullptr) + delete core; + delete coreThread; + } + delete global; +} + + +void Root::initializeTranslation() { + defaultTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + installTranslator(&defaultTranslator); + + QStringList shares = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + bool found = false; + for (QString share : shares) { + found = currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", share + "/l10n"); + if (found) { + break; + } + } + if (!found) { + currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", QCoreApplication::applicationDirPath()); + } + + installTranslator(¤tTranslator); +} + +void Root::initializeAppIcon() { + for (std::vector::size_type i = 0; i < appIconSizes.size(); ++i) + appIcon.addFile(":images/logo.svg", QSize(appIconSizes[i], appIconSizes[i])); + + Root::setWindowIcon(appIcon); +} + +bool Root::initializeSettings() { + QVariant vs = settings.value("style"); + if (vs.isValid()) { + QString style = vs.toString().toLower(); + if (style != "system") { + Shared::Global::setStyle(style); + } + } + + if (Shared::Global::supported("colorSchemeTools")) { + QVariant vt = settings.value("theme"); + if (vt.isValid()) { + QString theme = vt.toString(); + if (theme.toLower() != "system") { + Shared::Global::setTheme(theme); + } + } + } + + QString path = Shared::downloadsPathCheck(); + if (path.size() > 0) { + settings.setValue("downloadsPath", path); + } else { + qDebug() << "couldn't initialize directory for downloads, quitting"; + return false; + } + + return true; +} + +int Root::run() { + if (!componentsInitialized) + initializeComponents(); + + coreThread->start(); + int result = exec(); + qDebug("Event loop stopped"); + + if (result == 0) { + processEvents(); //I dont like all of this mess + if (coreThread->isRunning()) { //but it's the best solution for now + if (core != nullptr) { //Ideally, following line should never appear in the log + qDebug() << "Core is still seems to be running, killing manually"; + core->deleteLater(); + coreThread->quit(); + processEvents(); + core = nullptr; + } + coreThread->wait(); + } + } + + return result; +} + +void Root::initializeComponents() { + core = new Core::Squawk(); + coreThread = new QThread(); + core->moveToThread(coreThread); + gui = new Application(core); + + QObject::connect(&signalCatcher, &SignalCatcher::interrupt, gui, &Application::quit); + + QObject::connect(coreThread, &QThread::started, core, &Core::Squawk::start); + QObject::connect(gui, &Application::quitting, core, &Core::Squawk::stop); + + QObject::connect(core, &Core::Squawk::quit, core, &Core::Squawk::deleteLater); + QObject::connect(core, &Core::Squawk::destroyed, this, &Root::onCoreDestroyed); + QObject::connect(core, &Core::Squawk::destroyed, coreThread, &QThread::quit, Qt::QueuedConnection); + QObject::connect(coreThread, &QThread::finished, this, &Root::quit, Qt::QueuedConnection); + + componentsInitialized = true; +} bool Root::notify(QObject* receiver, QEvent* e) { try { return QApplication::notify(receiver, e); } catch(const std::runtime_error& e) { - qDebug() << "std::runtime_error in thread : " << QThread::currentThreadId(); - qDebug() << e.what(); + qDebug() << "std::runtime_error in thread:" << QThread::currentThreadId(); + qDebug() << "error message:" << e.what(); } catch(const std::exception& e) { - qDebug() << "std::exception in thread : " << QThread::currentThreadId(); - qDebug() << e.what(); + qDebug() << "std::exception in thread:" << QThread::currentThreadId(); + qDebug() << "error message:" << e.what(); } catch(const int& e) { - qDebug() << "int exception in thread : " << QThread::currentThreadId(); - qDebug() << e; + qDebug() << "integer exception in thread:" << QThread::currentThreadId(); + qDebug() << "thrown integer:" << std::to_string(e).c_str(); } catch(...) { - qDebug() << "exception thread : " << QThread::currentThreadId(); + qDebug() << "unhandled exception thread:" << QThread::currentThreadId(); } - qDebug() << "catch in notify "; + qDebug() << "Squawk is crashing..."; + exit(1); return false; } + +void Root::onCoreDestroyed() { + core = nullptr; +} diff --git a/main/root.h b/main/root.h index 02a82bc..003d9cb 100644 --- a/main/root.h +++ b/main/root.h @@ -18,11 +18,53 @@ #define ROOT_H #include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include "application.h" class Root : public QApplication { + Q_OBJECT public: Root(int& argc, char* argv[]); + ~Root(); bool notify(QObject* receiver, QEvent* e) override; + int run(); + + bool initializeSettings(); + +private slots: + void onCoreDestroyed(); + +private: + void initializeTranslation(); + void initializeAppIcon(); + void initializeComponents(); + +private: + static const std::vector appIconSizes; + + SignalCatcher signalCatcher; + QTranslator defaultTranslator; + QTranslator currentTranslator; + QIcon appIcon; + QSettings settings; + bool componentsInitialized; + + Shared::Global* global; + QThread* coreThread; + Core::Squawk* core; + Application* gui; + }; #endif // ROOT_H