diff --git a/src/app/main.cpp b/src/app/main.cpp index b0ca009b8c9..d6d0c8cc121 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -22,29 +22,20 @@ #include #include -#include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include #include +#include #include #include +#include #include -#include +#include #include +#include +#include +#include #include #include @@ -589,11 +580,12 @@ int main(int argc, char **argv) SharedTools::QtSingleApplication::setAttribute(Qt::AA_ShareOpenGLContexts); - int numberofArguments = static_cast(options.appArguments.size()); + int numberOfArguments = static_cast(options.appArguments.size()); - SharedTools::QtSingleApplication app((QLatin1String(Core::Constants::IDE_DISPLAY_NAME)), - numberofArguments, - options.appArguments.data()); + std::unique_ptr + appPtr(SharedTools::createApplication(QLatin1String(Core::Constants::IDE_DISPLAY_NAME), + numberOfArguments, options.appArguments.data())); + SharedTools::QtSingleApplication &app = *appPtr; QCoreApplication::setApplicationName(Core::Constants::IDE_CASED_ID); QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::IDE_VERSION_LONG)); QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)); diff --git a/src/shared/qtsingleapplication/qtsingleapplication.cpp b/src/shared/qtsingleapplication/qtsingleapplication.cpp index 4a79f4eee6b..0f8fa8b6d13 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.cpp +++ b/src/shared/qtsingleapplication/qtsingleapplication.cpp @@ -148,13 +148,11 @@ void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessag disconnect(pidPeer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); } - QWidget* QtSingleApplication::activationWindow() const { return actWin; } - void QtSingleApplication::activateWindow() { if (actWin) { @@ -164,4 +162,70 @@ void QtSingleApplication::activateWindow() } } +static const char s_freezeDetector[] = "QTC_FREEZE_DETECTOR"; + +static std::optional isUsingFreezeDetector() +{ + if (!qEnvironmentVariableIsSet(s_freezeDetector)) + return {}; + + bool ok = false; + const int threshold = qEnvironmentVariableIntValue(s_freezeDetector, &ok); + return ok ? threshold : 100; // default value 100ms +} + +class ApplicationWithFreezerDetector : public SharedTools::QtSingleApplication +{ +public: + ApplicationWithFreezerDetector(const QString &id, int &argc, char **argv) + : QtSingleApplication(id, argc, argv) + , m_align(21, QChar::Space) + {} + void setFreezeTreshold(std::chrono::milliseconds freezeAbove) { m_threshold = freezeAbove; } + + bool notify(QObject *receiver, QEvent *event) override { + using namespace std::chrono; + const auto start = system_clock::now(); + const QPointer p(receiver); + const QString className = QLatin1String(receiver->metaObject()->className()); + const QString name = receiver->objectName(); + + const bool ret = QtSingleApplication::notify(receiver, event); + + const auto end = system_clock::now(); + const auto freeze = duration_cast(end - start); + if (freeze > m_threshold) { + const QString time = QTime::currentTime().toString(Qt::ISODateWithMs); + qDebug().noquote() << QString("FREEZE [%1]").arg(time) + << "of" << freeze.count() << "ms, on:" << event; + const QString receiverMessage = name.isEmpty() + ? QString("receiver class: %1").arg(className) + : QString("receiver class: %1, object name: %2").arg(className, name); + qDebug().noquote() << m_align << receiverMessage; + if (!p) + qDebug().noquote() << m_align << "THE RECEIVER GOT DELETED inside the event filter!"; + } + return ret; + } + +private: + const QString m_align; + std::chrono::milliseconds m_threshold = std::chrono::milliseconds(100); +}; + +QtSingleApplication *createApplication(const QString &id, int &argc, char **argv) +{ + const std::optional freezeDetector = isUsingFreezeDetector(); + if (!freezeDetector) + return new SharedTools::QtSingleApplication(id, argc, argv); + + qDebug() << s_freezeDetector << "evn var is set. The freezes of main thread, above" + << *freezeDetector << "ms, will be reported."; + qDebug() << "Change the freeze detection threshold by setting the" << s_freezeDetector + << "env var to a different numeric value (in ms)."; + ApplicationWithFreezerDetector *app = new ApplicationWithFreezerDetector(id, argc, argv); + app->setFreezeTreshold(std::chrono::milliseconds(*freezeDetector)); + return app; +} + } // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.h b/src/shared/qtsingleapplication/qtsingleapplication.h index 2adbe185426..fdc485bd98c 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.h +++ b/src/shared/qtsingleapplication/qtsingleapplication.h @@ -46,4 +46,7 @@ private: bool block; }; +// Instantiates Freeze Detector when QTC_FREEZE_DETECTOR env var is set. +QtSingleApplication *createApplication(const QString &id, int &argc, char **argv); + } // namespace SharedTools