Bug 146538

Summary: Memory leak for a protected element having pending events in ImageLoader
Product: WebKit Reporter: kyounga <kyounga.ra>
Component: WebCore Misc.Assignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: beidson, cdumez, commit-queue, japhet
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Use RefPtr not calling ref/deref() directly
none
Use RefPtr not calling ref/deref() directly
beidson: review-
Use RefPtr not calling ref/deref() directly none

kyounga
Reported 2015-07-01 19:12:16 PDT
We found a memory leak possibility in ImageLoader. See the code below ==== ImageLoader::~ImageLoader() { .. if (m_elementIsProtected) element().deref(); } void ImageLoader::updatedHasPendingEvent() { bool wasProtected = m_elementIsProtected; m_elementIsProtected = m_hasPendingLoadEvent || m_hasPendingErrorEvent; if (wasProtected == m_elementIsProtected) return; if (m_elementIsProtected) { if (m_derefElementTimer.isActive()) m_derefElementTimer.stop(); else element().ref(); } else { ASSERT(!m_derefElementTimer.isActive()); m_derefElementTimer.startOneShot(0); } } void ImageLoader::timerFired() { element().deref(); } ==== Let's supposed that an protected element is to be "unprotected". The "m_elementIsProtected" flag is false immediately, but deref() is called later using Timer. If ImageLoader is destroyed before the timer is fired, the element's refCount never be zero. I didn't create a test case but there is logically 100% memory leak in this case.
Attachments
Use RefPtr not calling ref/deref() directly (3.66 KB, patch)
2015-07-01 19:26 PDT, kyounga
no flags
Use RefPtr not calling ref/deref() directly (3.66 KB, patch)
2015-07-01 23:30 PDT, kyounga
beidson: review-
Use RefPtr not calling ref/deref() directly (3.66 KB, patch)
2015-07-02 17:46 PDT, kyounga
no flags
kyounga
Comment 1 2015-07-01 19:26:32 PDT
Created attachment 255984 [details] Use RefPtr not calling ref/deref() directly
Brady Eidson
Comment 2 2015-07-01 22:19:06 PDT
Comment on attachment 255984 [details] Use RefPtr not calling ref/deref() directly View in context: https://bugs.webkit.org/attachment.cgi?id=255984&action=review > Source/WebCore/loader/ImageLoader.cpp:363 > + m_protectedElement= &element(); Type: Missing a space before the =. (Really bummed that check-webkit-style didn't get this) > Source/WebCore/loader/ImageLoader.cpp:372 > + m_protectedElement.clear(); This should be: m_protectedElement = nullptr;
kyounga
Comment 3 2015-07-01 23:26:08 PDT
(In reply to comment #2) > Comment on attachment 255984 [details] > Use RefPtr not calling ref/deref() directly > > View in context: > https://bugs.webkit.org/attachment.cgi?id=255984&action=review > > > Source/WebCore/loader/ImageLoader.cpp:363 > > + m_protectedElement= &element(); > > Type: Missing a space before the =. > > (Really bummed that check-webkit-style didn't get this) > > > Source/WebCore/loader/ImageLoader.cpp:372 > > + m_protectedElement.clear(); > > This should be: > m_protectedElement = nullptr; m_protectedElement is RefPtr. clear() will clear the internal pointer to nullptr. I will change the typo.
kyounga
Comment 4 2015-07-01 23:30:28 PDT
Created attachment 255993 [details] Use RefPtr not calling ref/deref() directly
Brady Eidson
Comment 5 2015-07-02 08:43:45 PDT
(In reply to comment #3) > (In reply to comment #2) > > Comment on attachment 255984 [details] > > Use RefPtr not calling ref/deref() directly > > > > View in context: > > https://bugs.webkit.org/attachment.cgi?id=255984&action=review > > > > > Source/WebCore/loader/ImageLoader.cpp:363 > > > + m_protectedElement= &element(); > > > > Type: Missing a space before the =. > > > > (Really bummed that check-webkit-style didn't get this) > > > > > Source/WebCore/loader/ImageLoader.cpp:372 > > > + m_protectedElement.clear(); > > > > This should be: > > m_protectedElement = nullptr; > > > m_protectedElement is RefPtr. > clear() will clear the internal pointer to nullptr. I know. Assigning a nullptr to a RefPtr is functionally the same as calling clear() on it. But when somebody not familiar with the code is reading it, and they come across a call to ".clear()", they don't necessarily know you're null'ing out a RefPtr. They might think you're calling "clear()" on some object that has a whole bunch of behavior inside of its ::clear() method. But by assigning nullptr, it's obvious to anybody reading the code "This is a pointer - it might be a raw pointer or one of our various types of smart pointers, but I know it's a pointer and this code is null'ing it out" This request is about readability by people not familiar with the code.
Brady Eidson
Comment 6 2015-07-02 08:45:05 PDT
Comment on attachment 255993 [details] Use RefPtr not calling ref/deref() directly View in context: https://bugs.webkit.org/attachment.cgi?id=255993&action=review > Source/WebCore/loader/ImageLoader.cpp:372 > - element().deref(); > + m_protectedElement.clear(); Change this to: m_protectedElement = nullptr; With this code, people have to ask themselves "what kind of object is this, and what does clear do?" With nullptr assignment, anybody not familiar with the code knows it is a pointer being null'ed out.
kyounga
Comment 7 2015-07-02 17:46:18 PDT
Created attachment 256057 [details] Use RefPtr not calling ref/deref() directly
kyounga
Comment 8 2015-07-02 17:48:55 PDT
(In reply to comment #6) > Comment on attachment 255993 [details] > Use RefPtr not calling ref/deref() directly > > View in context: > https://bugs.webkit.org/attachment.cgi?id=255993&action=review > > > Source/WebCore/loader/ImageLoader.cpp:372 > > - element().deref(); > > + m_protectedElement.clear(); > > Change this to: > m_protectedElement = nullptr; > > With this code, people have to ask themselves "what kind of object is this, > and what does clear do?" > With nullptr assignment, anybody not familiar with the code knows it is a > pointer being null'ed out. I thought calling clear() is more explicit. Also, I understand your thought. I attached a changed patch. Thanks for your comment.
Brady Eidson
Comment 9 2015-07-02 19:55:15 PDT
(In reply to comment #8) > (In reply to comment #6) > > Comment on attachment 255993 [details] > > Use RefPtr not calling ref/deref() directly > > > > View in context: > > https://bugs.webkit.org/attachment.cgi?id=255993&action=review > > > > > Source/WebCore/loader/ImageLoader.cpp:372 > > > - element().deref(); > > > + m_protectedElement.clear(); > > > > Change this to: > > m_protectedElement = nullptr; > > > > With this code, people have to ask themselves "what kind of object is this, > > and what does clear do?" > > With nullptr assignment, anybody not familiar with the code knows it is a > > pointer being null'ed out. > > I thought calling clear() is more explicit. Also, I understand your thought. > I attached a changed patch. > Thanks for your comment. FWIW, this discussion spawned https://bugs.webkit.org/show_bug.cgi?id=146556 in which we intend to remove RefPtr::clear altogether :)
WebKit Commit Bot
Comment 10 2015-07-03 14:56:37 PDT
Comment on attachment 256057 [details] Use RefPtr not calling ref/deref() directly Clearing flags on attachment: 256057 Committed r186267: <http://trac.webkit.org/changeset/186267>
WebKit Commit Bot
Comment 11 2015-07-03 14:56:40 PDT
All reviewed patches have been landed. Closing bug.
Note You need to log in before you can comment on or make changes to this bug.