Closed Bug 203596 Opened 23 years ago Closed 23 years ago

Memory leak of 52 bytes from 1 block allocated in FrameManager::CantRenderReplacedElement

Categories

(Core :: Layout, defect)

x86
Windows 2000
defect
Not set
normal

Tracking

()

VERIFIED FIXED

People

(Reporter: stephend, Assigned: dougt)

Details

(Keywords: memory-leak)

Attachments

(1 file)

Build: Latest trunk pull on Windows 2000 under Purify. Steps to Reproduce: 1. mozilla.exe -addressbook 2. Click 'New Card' 3. Type "S" into any field. 4. Hit Save. [W] MLK: Memory leak of 52 bytes from 1 block allocated in FrameManager::CantRenderReplacedElement(nsIPresContext *,nsIFrame *) Distribution of leaked blocks 52 bytes from 1 block of 52 bytes (0x0ace5ff0) Allocation location new(UINT) [new.cpp:23] FrameManager::CantRenderReplacedElement(nsIPresContext *,nsIFrame *) [nsFrameManager.cpp:1289] CantRenderReplacedElementEvent* ev; // Create a new event => ev = new CantRenderReplacedElementEvent(this, aFrame, mPresShell); // Add the event to our linked list of posted events ev->mNext = mPostedEvents; PresShell::CantRenderReplacedElement(nsIPresContext *,nsIFrame *) [nsPresShell.cpp:3985] nsIFrame* aFrame) { if (mFrameManager) { => return mFrameManager->CantRenderReplacedElement(aPresContext, aFrame); } return NS_OK; nsImageFrame::HandleLoadError(UINT,nsIPresShell *) [nsImageFrame.cpp:497] nsIFrame* primaryFrame = nsnull; aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame); aPresShell->CantRenderReplacedElement(mPresContext, => primaryFrame ? primaryFrame : this); return NS_ERROR_FRAME_REPLACED; } nsImageFrame::Init(nsIPresContext *,nsIContent *,nsIFrame *,nsStyleContext *,nsIFrame *) [nsImageFrame.cpp:330] PRBool loadBlocked = PR_FALSE; imageLoader->GetImageBlocked(&loadBlocked); rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, => presShell); } return rv; nsCSSFrameConstructor::InitAndRestoreFrame(nsIPresContext *,nsFrameConstructorState&,nsIContent *,nsIFrame *,nsStyleContext *,nsIFrame *,nsIFrame *) [nsCSSFrameConstructor.cpp:6832] // Initialize the frame rv = aNewFrame->Init(aPresContext, aContent, aParentFrame, => aStyleContext, aPrevInFlow); if (aState.mFrameState && aState.mFrameManager) { // Restore frame state for just the newly created frame. nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell *,nsIPresContext *,nsFrameConstructorState&,nsIContent *,nsIFrame *,nsIAtom *,int,nsStyleContext *,nsFrameItems&) [nsCSSFrameConstructor.cpp:4994] } rv = InitAndRestoreFrame(aPresContext, aState, aContent, => geometricParent, aStyleContext, nsnull, newFrame); if (rv == NS_ERROR_FRAME_REPLACED) { // The frame called CantRenderReplacedElement from inside Init(). That // failed to do anything useful, since the frame was not in the frame nsCSSFrameConstructor::ConstructFrameInternal(nsIPresShell *,nsIPresContext *,nsFrameConstructorState&,nsIContent *,nsIFrame *,nsIAtom *,int,nsStyleContext *,nsFrameItems&,int) [nsCSSFrameConstructor.cpp:7426] // Handle specific frame types nsresult rv = ConstructHTMLFrame(aPresShell, aPresContext, aState, aContent, aParentFrame, aTag, => aNameSpaceID, styleContext, aFrameItems); // Failing to find a matching HTML frame, try creating a specialized // XUL frame. This is temporary, pending planned factoring of this nsCSSFrameConstructor::ConstructFrame(nsIPresShell *,nsIPresContext *,nsFrameConstructorState&,nsIContent *,nsIFrame *,nsFrameItems&) [nsCSSFrameConstructor.cpp:7323] } // construct the frame rv = ConstructFrameInternal(aPresShell, aPresContext, aState, aContent, aParentFrame, => tag, nameSpaceID, styleContext, aFrameItems, PR_FALSE); if (NS_SUCCEEDED(rv) && pageBreakAfter) { // Construct the page break after ConstructPageBreakFrame(aPresShell, aPresContext, aState, aContent, nsCSSFrameConstructor::ProcessChildren(nsIPresShell *,nsIPresContext *,nsFrameConstructorState&,nsIContent *,nsIFrame *,int,nsFrameItems&,int,nsTableCreator *) [nsCSSFrameConstructor.cpp:12245] iter != last; ++iter) { rv = ConstructFrame(aPresShell, aPresContext, aState, nsCOMPtr<nsIContent>(*iter), => aFrame, aFrameItems); if (NS_FAILED(rv)) return rv;
found the problem
Assignee: other → dougt
Attachment #123522 - Flags: superreview?(dbaron)
Comment on attachment 123522 [details] [diff] [review] properly destroys plevent >+ delete ev; shouldn't this be PL_DestroyEvent also? otherwise the lock and cvar will be leaked. of course, if that other patch were in the tree...
yup. it should be (204963, right?)
Comment on attachment 123522 [details] [diff] [review] properly destroys plevent > // Post the event >- eventQueue->PostEvent(ev); >+ if (eventQueue->PostEvent(ev) == PR_FAILURE) { >+ NS_WARNING("Could not post CantRenderReplacedElementEvent"); >+ mPostedEvents = ev->mNext; >+ delete ev; >+ } > } > } Looking at PL_PostEvent, it looks like PR_FAILURE doesn't mean that it wasn't stored in the queue -- in fact, it looks like it will always be stored in the queue. So perhaps you should skip this half and just do the other half of the patch?
Agreed. Only the first part of the diff should be checked in.
Comment on attachment 123522 [details] [diff] [review] properly destroys plevent OK, then r+sr=dbaron on this part of the patch: >Index: html/base/src/nsFrameManager.cpp >=================================================================== >RCS file: /cvsroot/mozilla/layout/html/base/src/nsFrameManager.cpp,v >retrieving revision 1.147 >diff -u -1 -0 -r1.147 nsFrameManager.cpp >--- html/base/src/nsFrameManager.cpp 23 Apr 2003 00:43:03 -0000 1.147 >+++ html/base/src/nsFrameManager.cpp 16 May 2003 18:24:52 -0000 >@@ -1130,22 +1130,23 @@ > > NS_ASSERTION(NS_SUCCEEDED(rv) && eventQueue, > "will crash soon due to event holding dangling pointer to frame"); > if (NS_SUCCEEDED(rv) && eventQueue) { > PLEventQueue* plqueue; > > eventQueue->GetPLEventQueue(&plqueue); > NS_ASSERTION(plqueue, > "will crash soon due to event holding dangling pointer to frame"); > if (plqueue) { >- // Removes the event and destroys it >+ // Remove the event and then destroy it > PL_DequeueEvent(tmp, plqueue); >+ PL_DestroyEvent(tmp); > } > } > } > } > } > > void > FrameManager::HandlePLEvent(CantRenderReplacedElementEvent* aEvent) > { > #ifdef NOISY_EVENTS
Attachment #123522 - Flags: superreview?(dbaron)
Attachment #123522 - Flags: superreview+
Attachment #123522 - Flags: review+
uhm... i don't get it. nsEventQueue::PostEvent can return a failure code without queuing up the event. PL_PostEvent may not even get called. i think we may seriously have a problem in a lot of code if we ever get to the point where PL_PostEvent returns a failure code because most everywhere else we either call PL_DestroyEvent when nsIEventQueue::PostEvent fails or we call operator delete (which is definitely wrong). so, we have major bugs here...
incidentally it appears that PL_PostEvent will never fail on WIN32, but on other platforms it might. the fact that it leaves the event in the event queue means that we would crash if this ever happened. (not in the case of the frame manager code, but certainly in the case of a lot of other PostEvent call sites.)
darin, i think the problem that you mention is a problem throughout the mozilla code. The first part of this patch addresses the the fundemental problem in which we *never* delete these events. I would like to try to get this part into the tree for 1.4 and wait to address the 204963 post 1.4.
Attachment #123522 - Flags: approval1.4?
yeah, absolutely. that does make the most sense ;-)
Comment on attachment 123522 [details] [diff] [review] properly destroys plevent a=asa (on behalf of drivers) for checkin to 1.4
Attachment #123522 - Flags: approval1.4? → approval1.4+
Checking in html/base/src/nsFrameManager.cpp; /cvsroot/mozilla/layout/html/base/src/nsFrameManager.cpp,v <-- nsFrameManager.cpp new revision: 1.149; previous revision: 1.148 done
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
This is fixed. I verified it under a clean tree (debug) Win2000/Purify. Thanks!
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: