aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Szymon Tomasz Stefanek2010-01-11 04:03:07 +0000
committerGravatar Szymon Tomasz Stefanek2010-01-11 04:03:07 +0000
commita8e52442636bb66adfdf604b0097fa525621c27f (patch)
tree9037b34a76dccc00963412d782da156f63939a7b /src
parentquick fix (diff)
downloadKVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.tar.gz
KVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.tar.bz2
KVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.zip
Fixed a crash on exit after using the alias editor. Bad vtable.
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@3831 17fca916-40b9-46aa-a4ea-0a15b648b75c
Diffstat (limited to 'src')
-rw-r--r--src/kvilib/core/kvi_pointerhashtable.h10
-rw-r--r--src/kvirc/kvs/kvi_kvs_aliasmanager.cpp37
-rw-r--r--src/kvirc/kvs/kvi_kvs_aliasmanager.h11
-rw-r--r--src/modules/aliaseditor/aliaseditor.cpp49
4 files changed, 73 insertions, 34 deletions
diff --git a/src/kvilib/core/kvi_pointerhashtable.h b/src/kvilib/core/kvi_pointerhashtable.h
index 4d30257d9..b5e611d10 100644
--- a/src/kvilib/core/kvi_pointerhashtable.h
+++ b/src/kvilib/core/kvi_pointerhashtable.h
@@ -410,7 +410,8 @@ public:
{
if(!pData)return;
unsigned int uEntry = kvi_hash_hash(hKey,m_bCaseSensitive) % m_uSize;
- if(!m_pDataArray[uEntry])m_pDataArray[uEntry] = new KviPointerList<KviPointerHashTableEntry<Key,T> >(true);
+ if(!m_pDataArray[uEntry])
+ m_pDataArray[uEntry] = new KviPointerList<KviPointerHashTableEntry<Key,T> >(true);
for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[uEntry]->first();e;e = m_pDataArray[uEntry]->next())
{
if(kvi_hash_key_equal(e->hKey,hKey,m_bCaseSensitive))
@@ -421,7 +422,8 @@ public:
kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys);
kvi_hash_key_copy(hKey,e->hKey,m_bDeepCopyKeys);
}
- if(m_bAutoDelete)delete e->pData;
+ if(m_bAutoDelete)
+ delete e->pData;
e->pData = pData;
return;
}
@@ -536,8 +538,10 @@ public:
if(m_bAutoDelete)
delete ((T *)(e->pData));
}
- delete m_pDataArray[i];
+ KviPointerList<KviPointerHashTableEntry<Key,T> > * pList = m_pDataArray[i];
+ //delete m_pDataArray[i];
m_pDataArray[i] = 0;
+ delete pList;
}
}
m_uCount = 0;
diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp
index 2f4f5e5d6..5256f7afd 100644
--- a/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp
+++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp
@@ -39,6 +39,7 @@ KviKvsAliasManager::KviKvsAliasManager()
KviKvsAliasManager::~KviKvsAliasManager()
{
delete m_pAliasDict;
+ m_pAliasManager = 0;
}
void KviKvsAliasManager::init()
@@ -61,6 +62,42 @@ void KviKvsAliasManager::done()
delete KviKvsAliasManager::instance();
}
+void KviKvsAliasManager::add(const QString &szName,KviKvsScript * pAlias)
+{
+ // This piece of code, when inlined by gcc (i.e, placed in a header),
+ // shows an interesting problem.
+
+ // KviKvsPointerHashTable<>::replace() is a template and is likely to be inlined too.
+ // The internals of replace() use another template called KviKvsPointerHashTableEntry<>.
+ // When this function is called from a dynamically loaded shared library
+ // the internal template is likely to be instantiated in the shared library itself.
+ // Now if the shared library is unloaded, a dangling vtable pointer is stored
+ // in the inner template and it will die once we attempt to clear the m_pAliasDict ht.
+ //
+ // This happens for KviAliasEditor, for instance. In it's commit() function
+ // it called this method and caused the vtable pointer to be 0x7fffdfab0030.
+ //
+ // (gdb) info symbol 0x7fffdfab0030
+ // vtable for KviPointerList<KviPointerHashTableEntry<QString, KviKvsScript> > + 16 in section .data.rel.ro
+ // of /usr/local/lib/kvirc/4.0/modules/libkvialiaseditor.so <-- inside the module
+ //
+ // while the correct vtable (the one that appears when the add() function is called from somewhere else) is
+ //
+ //(gdb) info symbol 0x6bc210
+ // vtable for KviPointerList<KviPointerHashTableEntry<QString, KviKvsScript> > + 16 in section .rodata
+ // of /usr/local/bin/kvirc <-- inside the executable
+ //
+ // This is a linkage problem. Either caused by gcc itself, or maybe wrong flags
+ // passed by the cmake generated Makefiles. Gcc should notice that the symbol is already defined
+ // inside the executable and use that one instead.
+ //
+ // So finally, we can't inline this.
+
+ // The bad news is that this problem may pop up also in other pieces of code...
+ m_pAliasDict->replace(szName,pAlias);
+ emit aliasRefresh(szName);
+}
+
void KviKvsAliasManager::completeCommand(const QString &word,KviPointerList<QString> * matches)
{
KviPointerHashTableIterator<QString,KviKvsScript> it(*m_pAliasDict);
diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.h b/src/kvirc/kvs/kvi_kvs_aliasmanager.h
index 3db9545ed..ee142d272 100644
--- a/src/kvirc/kvs/kvi_kvs_aliasmanager.h
+++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.h
@@ -50,11 +50,7 @@ public:
KviPointerHashTable<QString,KviKvsScript> * aliasDict(){ return m_pAliasDict; };
const KviKvsScript * lookup(const QString & szName)
{ return m_pAliasDict->find(szName); };
- void add(const QString &szName,KviKvsScript * pAlias)
- {
- m_pAliasDict->replace(szName,pAlias);
- emit aliasRefresh(szName);
- };
+ void add(const QString &szName,KviKvsScript * pAlias);
bool remove(const QString & szName)
{ return m_pAliasDict->remove(szName); };
void clear()
@@ -64,10 +60,9 @@ public:
void load(const QString & filename);
void completeCommand(const QString &word,KviPointerList<QString> * matches);
- signals:
+signals:
-
- void aliasRefresh(const QString &);
+ void aliasRefresh(const QString &);
};
// namespaces are handled completly in the editing!
#endif //!_KVI_KVS_ALIASMANAGER_H_
diff --git a/src/modules/aliaseditor/aliaseditor.cpp b/src/modules/aliaseditor/aliaseditor.cpp
index 26716ab0f..a1ec6d41c 100644
--- a/src/modules/aliaseditor/aliaseditor.cpp
+++ b/src/modules/aliaseditor/aliaseditor.cpp
@@ -443,26 +443,27 @@ void KviAliasEditor::oneTimeSetup()
connect(KviKvsAliasManager::instance(),SIGNAL(aliasRefresh(const QString &)),this,SLOT(aliasRefresh(const QString &)));
m_pTreeWidget->sortItems(0,Qt::AscendingOrder);
}
+
void KviAliasEditor::aliasRefresh(const QString &szName)
{
- if(m_bSaving) return;
+ if(m_bSaving)
+ return;
KviAliasTreeWidgetItem * item;
KviKvsScript * alias = KviKvsAliasManager::instance()->aliasDict()->find(szName);
item = createFullAliasItem(szName);
if(item!=m_pLastEditedItem)
{
item->setBuffer(alias->code());
- } else {
- if(QMessageBox::warning(0,__tr2qs("OverWrite Current Alias"),
- __tr2qs("An external script has changed the alias you are currently editing. Do you want to accept the external changes?"),
- QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes)
- {
- return;
- } else {
- item->setBuffer(alias->code());
- m_pEditor->setText(alias->code());
- }
+ return;
}
+ if(
+ QMessageBox::warning(0,__tr2qs("OverWrite Current Alias"),
+ __tr2qs("An external script has changed the alias you are currently editing. Do you want to accept the external changes?"),
+ QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes
+ )
+ return;
+ item->setBuffer(alias->code());
+ m_pEditor->setText(alias->code());
}
void KviAliasEditor::itemRenamed(QTreeWidgetItem *it,int col)
@@ -1031,10 +1032,12 @@ void KviAliasEditor::appendSelectedItems(KviPointerList<KviAliasEditorTreeWidget
void KviAliasEditor::removeItemChildren(KviAliasEditorTreeWidgetItem *it)
{
- for (int i=0;i<it->childCount();i++)
+ while(it->childCount() > 0)
{
- if (it->child(i)->childCount()) removeItemChildren((KviAliasEditorTreeWidgetItem *)it->child(i));
- delete it->child(i);
+ KviAliasEditorTreeWidgetItem * pChild = (KviAliasEditorTreeWidgetItem *)(it->child(0));
+ if(pChild->childCount())
+ removeItemChildren(pChild);
+ delete pChild;
}
}
@@ -1075,7 +1078,8 @@ bool KviAliasEditor::removeItem(KviAliasEditorTreeWidgetItem *it,bool * pbYesToA
m_pLastEditedItem = 0;
if(it == m_pLastClickedItem)
m_pLastClickedItem = 0;
- if (it->childCount()) removeItemChildren(it);
+ if (it->childCount())
+ removeItemChildren(it);
delete it;
return true;
/*
@@ -1495,7 +1499,8 @@ void KviAliasEditor::currentItemChanged(QTreeWidgetItem *it,QTreeWidgetItem *)
void KviAliasEditor::recursiveCommit(KviAliasEditorTreeWidgetItem * it)
{
- if(!it)return;
+ if(!it)
+ return;
if(it->isAlias())
{
QString szName = buildFullItemName(it);
@@ -1506,13 +1511,10 @@ void KviAliasEditor::recursiveCommit(KviAliasEditorTreeWidgetItem * it)
KviKvsScript * a = new KviKvsScript(szName,((KviAliasTreeWidgetItem *)it)->buffer());
KviKvsAliasManager::instance()->add(szName,a);
return;
- } else
- {
- for (int i=0;i<it->childCount();i++)
- {
- recursiveCommit((KviAliasEditorTreeWidgetItem *) it->child(i));
- }
}
+
+ for (int i=0;i<it->childCount();i++)
+ recursiveCommit((KviAliasEditorTreeWidgetItem *) it->child(i));
}
void KviAliasEditor::commit()
@@ -1520,7 +1522,8 @@ void KviAliasEditor::commit()
m_bSaving = true;
saveLastEditedItem();
-// KviKvsAliasManager::instance()->clear();
+ KviKvsAliasManager::instance()->clear();
+
for(int i=0;i<m_pTreeWidget->topLevelItemCount();i++)
{
KviAliasEditorTreeWidgetItem *item=(KviAliasEditorTreeWidgetItem *)m_pTreeWidget->topLevelItem(i);