Just set a breakpoint to make sure -- GetPrimaryFrameFor isn't called
during mRootFrame->Destroy(presContext);
except via accessibility, and that's when it causes the crash.
I think this is the right patch -- I believe this is the order of
destruction that should have been used in the first place, but the
original writer of ::Destroy didn't forsee GPFF being used between when
the frames are destroyed and when the primary frame hash table is destroyed.
- Aaron
Aaron Leventhal wrote:
> I'm getting a crash when the JAWS screen reader asks for some
> information about a link in the old page as a new page is loading.
> This happens almost every time a new page is loaded by clicking on a
> link.
>
> It turns out nsFrameManager first destroys the frame tree, and then
> destroys the primary frame map second. The crash occurs because the
> JAWS screen reader is asking about the link that was clicked on in the
> old page when the window gets destroyed, but right before
> the frame map is destroyed. Essentially, GetPrimaryFrameFor thinks it
> still has a
> valid hash table, even though none of the frame pointers are valid. A
> *Bugscape* bug was filed on this crash (12117).
>
> The following small patch fixes the crash. It reorders the frame and
> primary frame hash table destruction in nsFrameManager::Destroy.
>
> I need to know if this is an acceptable fix
>
> Index: nsFrameManager.cpp
> ===================================================================
> RCS file: /cvsroot/mozilla/layout/html/base/src/nsFrameManager.cpp,v
> retrieving revision 1.102
> diff -u -1 -2 -r1.102 nsFrameManager.cpp
> --- nsFrameManager.cpp 16 Feb 2002 16:31:49 -0000 1.102
> +++ nsFrameManager.cpp 7 Mar 2002 04:09:09 -0000
> @@ -503,37 +503,42 @@
> NS_IMETHODIMP
> FrameManager::Destroy()
> {
> NS_ASSERTION(mPresShell, "Frame manager already shut down.");
>
> nsCOMPtr<nsIPresContext> presContext;
>
> mPresShell->GetPresContext(getter_AddRefs(presContext));
>
> // Destroy the frame hierarchy. Don't destroy the property lists
> until after
> // we've destroyed the frame hierarchy because some frames may expect
> to be
> // able to retrieve their properties during destruction
> mPresShell->SetIgnoreFrameDestruction(PR_TRUE);
> - if (mRootFrame) {
> - mRootFrame->Destroy(presContext);
> - mRootFrame = nsnull;
> - }
> -
> if (mPrimaryFrameMap.ops) {
> PL_DHashTableFinish(&mPrimaryFrameMap);
> mPrimaryFrameMap.ops = nsnull;
> }
> if (mPlaceholderMap.ops) {
> PL_DHashTableFinish(&mPlaceholderMap);
> mPlaceholderMap.ops = nsnull;
> }
> +
> + // Don't destroy the frame hierarchy until the frame map is destroyed.
> + // Otherwise something might call into GetPrimaryFrameFor and get a
> bogus frame
> + // For example, accessibility software in another process may ask for
> information
> + // about a node in a half-destroyed document
> + if (mRootFrame) {
> + mRootFrame->Destroy(presContext);
> + mRootFrame = nsnull;
> + }
> +
> delete mUndisplayedMap;
> DestroyPropertyList(presContext);
>
> // If we're not going to be used anymore, we should revoke the
> // pending |CantRenderReplacedElementEvent|s being sent to us.
> nsresult rv = RevokePostedEvents();
> NS_ASSERTION(NS_SUCCEEDED(rv), "RevokePostedEvents failed: might
> crash");
>
>
>
> Thanks,
> Aaron
>
>