[kontact] [Bug 370646] Crash when opening Kontact preferences

RJVB via KDE Bugzilla bugzilla_noreply at kde.org
Fri Oct 14 21:17:17 BST 2016


https://bugs.kde.org/show_bug.cgi?id=370646

--- Comment #5 from RJVB <rjvbertin at gmail.com> ---
I don't understand how or why dynamically allocated memory can go stale when
the shared library which allocated it is unloaded, but apparently something
like that happens.

When I replace libnoteshared's attributeregistrar's mechanism with one that
create a global class instance when the library is loaded, I can clearly see
that instance being destroyed. I'll have a look at the backtrace leading into
that dtor, but meanwhile, here's a fix. It extends the AttributeFactory with a
method that returns the newly created attribute instance, and (a circuitous)
one that allows to unregister attributes.
The resulting libraries are ABI compatible, and Kontact no longer crashes

Patch for kdepimlibs4:
------------------------------------
diff --git akonadi/attributefactory.cpp akonadi/attributefactory.cpp
index 47a8839..51306f0 100644
--- akonadi/attributefactory.cpp
+++ akonadi/attributefactory.cpp
@@ -30,6 +30,7 @@
 #include "entityannotationsattribute.h"

 #include <KGlobal>
+#include <KDebug>

 #include <QtCore/QHash>

@@ -79,7 +80,18 @@ class StaticAttributeFactory : public AttributeFactory
 public:
     StaticAttributeFactory()
         : AttributeFactory()
-        , initialized(false) {}
+        , initialized(false)
+        , notDeleted(0) {
+        skipList << QLatin1String("NoteDisplayAttribute")
+            << QLatin1String("NoteAlarmAttribute")
+            << QLatin1String("KJotsLockAttribute")
+            << QLatin1String("showfoldernotesattribute");
+    }
+    ~StaticAttributeFactory() {
+        if (notDeleted > 0) {
+            kWarning(5250) << Q_FUNC_INFO << "attributes not deleted:" <<
notDeleted;
+        }
+    }
     void init() {
         if (initialized) {
             return;
@@ -98,6 +110,8 @@ public:
         AttributeFactory::registerAttribute<TagAttribute>();
     }
     bool initialized;
+    size_t notDeleted;
+    QStringList skipList;
 };

 K_GLOBAL_STATIC(StaticAttributeFactory, s_attributeInstance)
@@ -113,6 +127,9 @@ class AttributeFactory::Private
 {
 public:
     QHash<QByteArray, Attribute *> attributes;
+    Private() {
+        attributes.clear();
+    }
 };

 AttributeFactory *AttributeFactory::self()
@@ -132,18 +149,35 @@ AttributeFactory::~ AttributeFactory()
     delete d;
 }

+#include <QDebug>
 void AttributeFactory::registerAttribute(Attribute *attr)
 {
     Q_ASSERT(attr);
     Q_ASSERT(!attr->type().contains(' ') && !attr->type().contains('\'') &&
!attr->type().contains('"'));
     QHash<QByteArray, Attribute *>::Iterator it =
d->attributes.find(attr->type());
     if (it != d->attributes.end()) {
-        delete *it;
+//         if
(!s_attributeInstance->skipList.contains(QLatin1String(attr->type()))) {
+            delete *it;
+//         } else {
+//             s_attributeInstance->notDeleted += 1;
+//         }
         d->attributes.erase(it);
     }
     d->attributes.insert(attr->type(), attr);
 }

+void AttributeFactory::unRegisterAttribute(Attribute *attr)
+{
+    Q_ASSERT(attr);
+    Q_ASSERT(!attr->type().contains(' ') && !attr->type().contains('\'') &&
!attr->type().contains('"'));
+    kDebug(5250) << Q_FUNC_INFO << "deleting entry for type" << attr->type()
<< attr;
+    QHash<QByteArray, Attribute *>::Iterator it =
d->attributes.find(attr->type());
+    if (it != d->attributes.end()) {
+        delete *it;
+        d->attributes.erase(it);
+    }
+}
+
 Attribute *AttributeFactory::createAttribute(const QByteArray &type)
 {
     Attribute *attr = self()->d->attributes.value(type);
diff --git akonadi/attributefactory.h akonadi/attributefactory.h
index 647b67e..be3b471 100644
--- akonadi/attributefactory.h
+++ akonadi/attributefactory.h
@@ -60,6 +60,16 @@ public:
     {
         AttributeFactory::self()->registerAttribute(new T);
     }
+    template <typename T> inline static T *getRegisteredAttribute()
+    {
+        T *attr = new T;
+        AttributeFactory::self()->registerAttribute(attr);
+        return attr;
+    }
+    inline static void deRegisterAttribute(Attribute *attr)
+    {
+        AttributeFactory::self()->unRegisterAttribute(attr);
+    }

     /**
      * Creates an entity attribute object of the given type.
@@ -76,6 +86,7 @@ protected:
 private:
     static AttributeFactory *self();
     void registerAttribute(Attribute *attribute);
+    void unRegisterAttribute(Attribute *attribute);

     class Private;
     Private *const d;
------------------------------------

Patch for kdepim4:
------------------------------------
diff --git noteshared/attributes/attributeregistrar.cpp
noteshared/attributes/attributeregistrar.cpp
index cdcc949..56a61c0 100644
--- noteshared/attributes/attributeregistrar.cpp
+++ noteshared/attributes/attributeregistrar.cpp
@@ -22,19 +22,46 @@

 #include <akonadi/attributefactory.h>

+#include <KGlobal>
+#include <KDebug>
+
 namespace {

 // Anonymous namespace; function is invisible outside this file.
+
+class NoteSharedRegistrar {
+public:
+    NoteSharedRegistrar()
+    {
+      kDebug(5500) << Q_FUNC_INFO << this;
+      displayAttr =
Akonadi::AttributeFactory::getRegisteredAttribute<NoteShared::NoteDisplayAttribute>();
+      alarmAttr =
Akonadi::AttributeFactory::getRegisteredAttribute<NoteShared::NoteAlarmAttribute>();
+      lockAttr =
Akonadi::AttributeFactory::getRegisteredAttribute<NoteShared::NoteLockAttribute>();
+      showAttr =
Akonadi::AttributeFactory::getRegisteredAttribute<NoteShared::ShowFolderNotesAttribute>();
+    }
+    ~NoteSharedRegistrar()
+    {
+      kDebug(5500) << Q_FUNC_INFO << this;
+      Akonadi::AttributeFactory::deRegisterAttribute(displayAttr);
+      Akonadi::AttributeFactory::deRegisterAttribute(alarmAttr);
+      Akonadi::AttributeFactory::deRegisterAttribute(lockAttr);
+      Akonadi::AttributeFactory::deRegisterAttribute(showAttr);
+    }
+    NoteShared::NoteDisplayAttribute *displayAttr;
+    NoteShared::NoteAlarmAttribute *alarmAttr;
+    NoteShared::NoteLockAttribute *lockAttr;
+    NoteShared::ShowFolderNotesAttribute *showAttr;
+};
+K_GLOBAL_STATIC(NoteSharedRegistrar, s_registrarInstance)
+
 bool dummy()
 {
- 
Akonadi::AttributeFactory::registerAttribute<NoteShared::NoteDisplayAttribute>();
- 
Akonadi::AttributeFactory::registerAttribute<NoteShared::NoteAlarmAttribute>();
- 
Akonadi::AttributeFactory::registerAttribute<NoteShared::NoteLockAttribute>();
- 
Akonadi::AttributeFactory::registerAttribute<NoteShared::ShowFolderNotesAttribute>();
-  return true;
+    kDebug(5500) << "NoteSharedRegistrar=" << s_registrarInstance;
+    return s_registrarInstance != NULL;
 }

 // Called when this library is loaded.
 const bool registered = dummy();

+
 } // namespace
------------------------------------

-- 
You are receiving this mail because:
You are the assignee for the bug.



More information about the Kdepim-bugs mailing list