Bug 420055 - New shutdown crash, patch=aaronlev, r=me, sr=mconnor, approval1.9b4+=mconnor,beltzner
authorsurkov.alexander@gmail.com
Fri, 29 Feb 2008 07:38:35 -0800
changeset 12438 43c09f485386acd3c35ad10d265e1eec3c78199e
parent 12437 48cc7fe71b9ba060451851916ed4c4b0af8cdb24
child 12439 57ad39078a965cda8082973c8ae15d56f11a18cd
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme, mconnor, approval1.9b4
bugs420055
milestone1.9b4pre
Bug 420055 - New shutdown crash, patch=aaronlev, r=me, sr=mconnor, approval1.9b4+=mconnor,beltzner
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessNode.h
accessible/src/base/nsDocAccessible.cpp
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -81,16 +81,17 @@
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
 nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
 nsITimer *nsAccessNode::gDoCommandTimer = 0;
 nsIDOMNode *nsAccessNode::gLastFocusedNode = 0;
 PRBool nsAccessNode::gIsAccessibilityActive = PR_FALSE;
+PRBool nsAccessNode::gIsShuttingDownApp = PR_FALSE;
 PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
 PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
 nsAccessNodeHashtable nsAccessNode::gGlobalDocAccessibleCache;
 
 nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
 
 nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
 nsIAccessibilityService *nsAccessNode::GetAccService()
@@ -308,24 +309,26 @@ void nsAccessNode::ShutdownXPAccessibili
 {
   // Called by nsAccessibilityService::Shutdown()
   // which happens when xpcom is shutting down
   // at exit of program
 
   if (!gIsAccessibilityActive) {
     return;
   }
+  gIsShuttingDownApp = PR_TRUE;
+
   NS_IF_RELEASE(gStringBundle);
   NS_IF_RELEASE(gKeyStringBundle);
   NS_IF_RELEASE(gDoCommandTimer);
   NS_IF_RELEASE(gLastFocusedNode);
   NS_IF_RELEASE(sAccService);
 
   nsApplicationAccessibleWrap::Unload();
-  gGlobalDocAccessibleCache.Enumerate(ClearDocCacheEntry, nsnull);
+  ClearCache(gGlobalDocAccessibleCache);
 
   // Release gApplicationAccessible after everything else is shutdown
   // so we don't accidently create it again while tearing down root accessibles
   NS_IF_RELEASE(gApplicationAccessible);
   gApplicationAccessible = nsnull;  
 
   gIsAccessibilityActive = PR_FALSE;
   NotifyA11yInitOrShutdown();
@@ -791,24 +794,16 @@ nsAccessNode::GetCacheEntry(nsAccessNode
 PLDHashOperator nsAccessNode::ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
 {
   nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
   privateAccessNode->Shutdown();
 
   return PL_DHASH_REMOVE;
 }
 
-PLDHashOperator nsAccessNode::ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
-{
-  nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
-  privateAccessNode->Shutdown();
-
-  return PL_DHASH_NEXT; // nsDocAccessible::Shutdown() removes the doc from doc cache
-}
-
 void
 nsAccessNode::ClearCache(nsAccessNodeHashtable& aCache)
 {
   aCache.Enumerate(ClearCacheEntry, nsnull);
 }
 
 already_AddRefed<nsIDOMNode> nsAccessNode::GetCurrentFocus()
 {
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -93,17 +93,16 @@ class nsAccessNode: public nsIAccessNode
     // Static methods for handling per-document cache
     static void PutCacheEntry(nsAccessNodeHashtable& aCache,
                               void* aUniqueID, nsIAccessNode *aAccessNode);
     static void GetCacheEntry(nsAccessNodeHashtable& aCache,
                               void* aUniqueID, nsIAccessNode **aAccessNode);
     static void ClearCache(nsAccessNodeHashtable& aCache);
 
     static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
-    static PLDHashOperator PR_CALLBACK ClearDocCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
 
     // Static cache methods for global document cache
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocument *aDocument);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIWeakReference *aWeakShell);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDocShellTreeItem *aContainer, PRBool aCanCreate = PR_FALSE);
     static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDOMNode *aNode);
 
     static already_AddRefed<nsIDOMNode> GetDOMNodeForContainer(nsISupports *aContainer);
@@ -143,16 +142,17 @@ protected:
      */
     static void NotifyA11yInitOrShutdown();
 
     // Static data, we do our own refcounting for our static data
     static nsIStringBundle *gStringBundle;
     static nsIStringBundle *gKeyStringBundle;
     static nsITimer *gDoCommandTimer;
     static PRBool gIsAccessibilityActive;
+    static PRBool gIsShuttingDownApp;
     static PRBool gIsCacheDisabled;
     static PRBool gIsFormFillEnabled;
 
     static nsAccessNodeHashtable gGlobalDocAccessibleCache;
 
 private:
   static nsIAccessibilityService *sAccService;
   static nsApplicationAccessibleWrap *gApplicationAccessible;
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -546,17 +546,19 @@ NS_IMETHODIMP nsDocAccessible::Shutdown(
       // Make sure we release the kung fu death grip which is always
       // there when there are still events left to be fired
       NS_RELEASE_THIS();
     }
   }
 
   // Remove from the cache after other parts of Shutdown(), so that Shutdown() procedures
   // can find the doc or root accessible in the cache if they need it.
-  gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
+  // We don't do this during ShutdownAccessibility() because that is already clearing the cache
+  if (!gIsShuttingDownApp)
+    gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
 
   return NS_OK;
 }
 
 void nsDocAccessible::ShutdownChildDocuments(nsIDocShellTreeItem *aStart)
 {
   nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
   if (treeNode) {