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
This commit is contained in:
dbaron%dbaron.org
2006-04-20 21:38:29 +00:00
parent f50d3f03b8
commit aa17005653
3 changed files with 31 additions and 17 deletions

View File

@@ -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<nsIEventListenerManager> 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()) {

View File

@@ -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<nsIEventListenerManager> 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()) {

View File

@@ -228,9 +228,7 @@ public:
~EventListenerManagerMapEntry()
{
if (mListenerManager) {
mListenerManager->SetListenerTarget(nsnull);
}
NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
}
private: