Closed Bug 293534 Opened 20 years ago Closed 20 years ago

reloading with bfcache will crash Camino (nsDocShell::RestorePresentation(nsISHEntry*, int, int*) + 0x72c)

Categories

(Core :: DOM: Navigation, defect)

PowerPC
macOS
defect
Not set
critical

Tracking

()

VERIFIED FIXED

People

(Reporter: torben, Assigned: bryner)

References

()

Details

(Keywords: crash)

Attachments

(3 files)

Camino 2005050908 (v0.8+) (Found when trying to reproduce bug 245026) With bfcache enabled (browser.sessionhistory.max_viewers, 5) Camino will crash when you try to reload the url. No crash with bfcache turned off. Curiously Firefox (same build date) does _not_ crash with bfcache turned on. Might, or might not, be related to bug 292969 and/or bug 292970. Steps to reproduce: 1. Go to http://www.dioceseofstasaph.org.uk/ 2. Click on a link to "Diocesesan organisations" in the left column 3. Click the reload button Expected result: Reload page Actual result: Crash Trackback ID TB5704257M, crashlog coming up
Attached file Crash log
Flags: blocking-aviary1.1?
Keywords: crash
[Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b2) Gecko/20050510] (nightly) (W98SE) Confirmation: MozillaAS doesn't crash at step 3 either. (bug I can get bug 293698 going Back at a fourth step)
Severity: normal → critical
Attached patch patchSplinter Review
The problem here happens as follows: - The site contains a <frameset> with a single <frame> - When you click a link in the frame, the session history tree is cloned; the clone does not have any cached presentation. The original history tree (a parent entry and one child) has cached content viewers for both the parent and the child. - When you reload, the <frame> and its corresponding docshell are destroyed. The child history entry's viewer now has a dangling container pointer. - Go to restore the child history entry -> crash There are basically 3 things we can do: - hold a strong reference to the docshell; swap it back into the docshell tree when restoring the <frame> - hold a weak reference; bail on restoring the presentation if the docshell has gone away - hold a weak reference; try to restore the presentation into the _new_ docshell if the docshell has gone away I've opted to go for the second one. This might be worth revisiting if it affects a significant number of sites / use cases, but the other options seem pretty scary to me. I originally wanted to do this just by making Open() fail, but it turns out that we don't unhook the old content viewer correctly when that happens, leading to crashes. I just added an up-front check that the container of the stored content viewer is in fact the docshell we're restoring it to, which is a good invariant even if having Open() fail worked as expected.
Attachment #183352 - Flags: superreview?(bzbarsky)
Attachment #183352 - Flags: review?(bzbarsky)
In addition to this: + if (container != nsCOMPtr<nsISupports>(do_QueryInterface(NS_STATIC_CAST(nsIDocShell*, this)))) { +#ifdef DEBUG_PAGE_CACHE + printf("No valid container, not restoring presentation\n"); +#endif + return NS_OK; + } I wonder if it would make sense to clear out the whole presentation on the history entry...
FWIW, my Camino won't build with the above patch (attachment (id=183352)) nsDocShell.cpp: In member function `nsresult nsDocShell::RestorePresentation(nsISHEntry*, int, PRBool*)': nsDocShell.cpp:5180: error: `uri' undeclared (first use this function) nsDocShell.cpp:5180: error: (Each undeclared identifier is reported only once for each function it appears in.)
Comment on attachment 183352 [details] [diff] [review] patch >Index: docshell/base/nsDocShell.cpp > #ifdef DEBUG_PAGE_CACHE >+ nsCOMPtr<nsIURI> uri; >+ aSHEntry->GetURI(getter_AddRefs(uri)); |uri| is passed to SetCurrentURI at the end of this method, so we can't move getting it into this ifdef.... >@@ -4970,6 +4970,21 @@ nsDocShell::RestorePresentation(nsISHEnt >+ if (container != nsCOMPtr<nsISupports>(do_QueryInterface(NS_STATIC_CAST(nsIDocShell*, this)))) { I'd prefer: if (!::SameCOMIdentity(container, GetAsSupports(this))) { here. And yes, clearing out the presentation on the history entry when we hit this case makes a lot of sense to me. >Index: layout/base/nsDocumentViewer.cpp >@@ -610,10 +611,7 @@ DocumentViewerImpl::GetContainer(nsISupp >+ return CallQueryReferent(mContainer.get(), aResult); Won't that crash if mContainer is null (eg a container was never set)? Is that something we should worry about? If so, may be worth using do_QueryReferent and then swap() here. >@@ -1466,13 +1471,19 @@ DocumentViewerImpl::SetDOMDocument(nsIDO >+ nsCOMPtr<nsIScriptGlobalObject> global; >+ if (requestor) { >+ CallGetInterface(requestor.get(), >+ NS_STATIC_CAST(nsIScriptGlobalObject**, >+ getter_AddRefs(global))); >+ } Is this not using do_GetInterface(requestor); just to avoid an extra QI? If so, I'd go with the extra QI and clearer code... but either way. >@@ -4018,7 +4032,14 @@ DocumentViewerImpl::OnDonePrinting() >+ nsCOMPtr<nsIDOMWindowInternal> win; >+ if (requestor) { >+ CallGetInterface(requestor.get(), >+ NS_STATIC_CAST(nsIDOMWindowInternal**, >+ getter_AddRefs(win))); >+ } Same here. r+sr=bzbarsky with the nits picked.
Attachment #183352 - Flags: superreview?(bzbarsky)
Attachment #183352 - Flags: superreview+
Attachment #183352 - Flags: review?(bzbarsky)
Attachment #183352 - Flags: review+
Attached file Crash log 2
Camino will still crash with this patch (after moving the definition of uri outside the #ifdef or #ifdef'ing the SetCurrentURI) if after reloading the page I click on the link to "Diocesesan organisations" again. The crash now happens in nsChildView::Destroy().
(In reply to comment #6) > >@@ -1466,13 +1471,19 @@ DocumentViewerImpl::SetDOMDocument(nsIDO > >+ nsCOMPtr<nsIScriptGlobalObject> global; > >+ if (requestor) { > >+ CallGetInterface(requestor.get(), > >+ NS_STATIC_CAST(nsIScriptGlobalObject**, > >+ getter_AddRefs(global))); > >+ } > > Is this not using do_GetInterface(requestor); just to avoid an extra QI? If > so, I'd go with the extra QI and clearer code... but either way. > Yep, trying to avoid the extra QI when we already have an nsIInterfaceRequestor. I wonder if it would make more sense to add an overloaded do_GetInterface() implementation for nsIInterfaceRequestor*.
I'll do a Camino build this afternoon and try to figure out what's going on. (In reply to comment #7) > Created an attachment (id=183434) [edit] > Crash log 2 > > Camino will still crash with this patch (after moving the definition of uri > outside the #ifdef or #ifdef'ing the SetCurrentURI) if after reloading the page > I click on the link to "Diocesesan organisations" again. The crash now happens > in nsChildView::Destroy().
Comment on attachment 183352 [details] [diff] [review] patch I'm not seeing Camino crash using this patch. I did address Boris's comment regarding possible crash with CallQueryReferent, so maybe that's the reason. Either way, I'd like to get this in.
Attachment #183352 - Flags: approval1.8b2?
Comment on attachment 183352 [details] [diff] [review] patch a=me with comments addressed. /be
Attachment #183352 - Flags: approval1.8b2? → approval1.8b2+
checked in
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
crashed Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b2) Gecko/20050514 I know this build doesn´t contain the patch, and I couldn´t reproduce the crash. I´ve seen some sort of runtime error, didn´t care about text or number, as I wanted to reproduce after enabling talkback by deleting compreg.dat.
Blocks: 294236
No more crashes for me either with the checked in patch.
Status: RESOLVED → VERIFIED
Flags: blocking-aviary1.1?
Component: History: Session → Document Navigation
QA Contact: history.session → docshell
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: