From aa1700565326f525c10a7a2926445ed2574b9ad2 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Thu, 20 Apr 2006 21:38:29 +0000 Subject: [PATCH] Disconnect and release the event listener manager after removing the entry from the hash table to avoid crashes caused by re-entry into hash table code. b=334177 r+sr=jst a=dveditz git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_0_BRANCH@194994 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/base/src/nsGenericDOMDataNode.cpp | 18 +++++++++++-- mozilla/content/base/src/nsGenericElement.cpp | 26 ++++++++++--------- mozilla/content/base/src/nsGenericElement.h | 4 +-- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 9b710c4d0ad..486b9c7f6fb 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -65,8 +65,22 @@ nsGenericDOMDataNode::nsGenericDOMDataNode(nsIDocument *aDocument) nsGenericDOMDataNode::~nsGenericDOMDataNode() { if (CouldHaveEventListenerManager()) { - PL_DHashTableOperate(&nsGenericElement::sEventListenerManagersHash, - this, PL_DHASH_REMOVE); + EventListenerManagerMapEntry *entry = + NS_STATIC_CAST(EventListenerManagerMapEntry *, + PL_DHashTableOperate(&nsGenericElement:: + sEventListenerManagersHash, this, + PL_DHASH_LOOKUP)); + if (PL_DHASH_ENTRY_IS_BUSY(entry)) { + nsCOMPtr listenerManager; + listenerManager.swap(entry->mListenerManager); + // Remove the entry and *then* do operations that could cause further + // modification of sEventListenerManagersHash. See bug 334177. + PL_DHashTableRawRemove(&nsGenericElement:: + sEventListenerManagersHash, entry); + if (listenerManager) { + listenerManager->SetListenerTarget(nsnull); + } + } } if (CouldHaveRangeList()) { diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 262d0db6bbc..0e77080e075 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -883,21 +883,23 @@ nsGenericElement::~nsGenericElement() } if (HasEventListenerManager()) { -#ifdef DEBUG - { - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&sEventListenerManagersHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have a listener manager list, " + EventListenerManagerMapEntry *entry = + NS_STATIC_CAST(EventListenerManagerMapEntry *, + PL_DHashTableOperate(&sEventListenerManagersHash, this, + PL_DHASH_LOOKUP)); + NS_ASSERTION(!PL_DHASH_ENTRY_IS_FREE(entry), + "Huh, our bit says we have a listener manager list, " "but there's nothing in the hash!?!!"); + if (PL_DHASH_ENTRY_IS_BUSY(entry)) { + nsCOMPtr listenerManager; + listenerManager.swap(entry->mListenerManager); + // Remove the entry and *then* do operations that could cause further + // modification of sEventListenerManagersHash. See bug 334177. + PL_DHashTableRawRemove(&sEventListenerManagersHash, entry); + if (listenerManager) { + listenerManager->SetListenerTarget(nsnull); } } -#endif - - PL_DHashTableOperate(&sEventListenerManagersHash, this, PL_DHASH_REMOVE); } if (HasDOMSlots()) { diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index 51f6bb7d80a..2006f3d6050 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -228,9 +228,7 @@ public: ~EventListenerManagerMapEntry() { - if (mListenerManager) { - mListenerManager->SetListenerTarget(nsnull); - } + NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM"); } private: