Fix SEGV (by circular ownership) at exit
authorStephan Beyer <s-beyer@gmx.net>
Wed, 24 Jun 2020 11:50:17 +0000 (13:50 +0200)
committerStephan Beyer <s-beyer@gmx.net>
Wed, 24 Jun 2020 11:50:17 +0000 (13:50 +0200)
Commit a12205f322d43476230881192616e47c9cf786ef (PR #1891) introduced
a circular ownership: qmlRegisterSingletonType<Systray>(...) makes the
QQmlEngine own the resulting singleton Systray instance, however, the
QQmlEngine _trayEngine itself is owned by the Systray instance. This
circular ownership results in a crash when the destructor of Systray
calls the destructor of _trayEngine which attempts to call the destructor
of Systray.

This commit solves this problem by making ownCloudGui, which is the
parent of Systray, the parent of the _trayEngine.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
src/gui/owncloudgui.cpp
src/gui/systray.cpp
src/gui/systray.h

index ef335ffed0a72496ec028283b0f51bb27148e367..5dc280bdc8ed29ae93ac73c55df790dd269329ec 100644 (file)
@@ -32,6 +32,7 @@
 #include "cloudproviders/cloudprovidermanager.h"
 #endif
 
+#include <QQmlApplicationEngine>
 #include <QDesktopServices>
 #include <QDir>
 #include <QMessageBox>
@@ -66,7 +67,7 @@ ownCloudGui::ownCloudGui(Application *parent)
     , _app(parent)
 {
     _tray = Systray::instance();
-    _tray->setParent(this);
+    _tray->setTrayEngine(new QQmlApplicationEngine(this));
     // for the beginning, set the offline icon until the account was verified
     _tray->setIcon(Theme::instance()->folderOfflineIcon(/*systray?*/ true));
 
index a2b570970ccee3319a6bd7339f0143d148d95d83..0cb3c86a6cf0bfcbbe1990b159c1ef9fc2a2e3ff 100644 (file)
@@ -49,13 +49,17 @@ Systray *Systray::instance()
     return _instance;
 }
 
-Systray::Systray()
-    : QSystemTrayIcon(nullptr)
-    , _trayEngine(new QQmlApplicationEngine(this))
+void Systray::setTrayEngine(QQmlApplicationEngine *trayEngine)
 {
+    _trayEngine = trayEngine;
+
     _trayEngine->addImportPath("qrc:/qml/theme");
     _trayEngine->addImageProvider("avatars", new ImageProvider);
+}
 
+Systray::Systray()
+    : QSystemTrayIcon(nullptr)
+{
     qmlRegisterSingletonType<UserModel>("com.nextcloud.desktopclient", 1, 0, "UserModel",
         [](QQmlEngine *, QJSEngine *) -> QObject * {
             return UserModel::instance();
@@ -83,18 +87,22 @@ Systray::Systray()
 
 void Systray::create()
 {
-    if (!AccountManager::instance()->accounts().isEmpty()) {
-        _trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
+    if (_trayEngine) {
+        if (!AccountManager::instance()->accounts().isEmpty()) {
+            _trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
+        }
+        _trayEngine->load(QStringLiteral("qrc:/qml/src/gui/tray/Window.qml"));
     }
-    _trayEngine->load(QStringLiteral("qrc:/qml/src/gui/tray/Window.qml"));
     hideWindow();
     emit activated(QSystemTrayIcon::ActivationReason::Unknown);
 }
 
 void Systray::slotNewUserSelected()
 {
-    // Change ActivityModel
-    _trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
+    if (_trayEngine) {
+        // Change ActivityModel
+        _trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
+    }
 
     // Rebuild App list
     UserAppsModel::instance()->buildAppList();
index 0cb9249f6c3f926bd505c1a2a2666cd817f3d407..cffa4f8437755217f63846d427309c1b95c2e640 100644 (file)
@@ -49,6 +49,7 @@ public:
     enum class TaskBarPosition { Bottom, Left, Top, Right };
     Q_ENUM(TaskBarPosition);
 
+    void setTrayEngine(QQmlApplicationEngine *trayEngine);
     void create();
     void showMessage(const QString &title, const QString &message, MessageIcon icon = Information);
     void setToolTip(const QString &tip);
@@ -89,7 +90,7 @@ private:
 
     bool _isOpen = false;
     bool _syncIsPaused = false;
-    QQmlApplicationEngine *_trayEngine;
+    QQmlApplicationEngine *_trayEngine = nullptr;
 };
 
 } // namespace OCC