WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
12850
Event listener leaks seen @ gmail.com
https://bugs.webkit.org/show_bug.cgi?id=12850
Summary
Event listener leaks seen @ gmail.com
Feng Qian
Reported
2007-02-21 21:53:06 PST
You need a gmail account. In KJS::Collector::collect(), before exiting the function, log heap.numLiveObjects. After visiting GMail, close the window, open a new one, there are still >10k live objects. I looked further, there are protected objects (FunctionImp) that cannot be reclaimed. These protected FunctionImp also causes other objects to leak.
Attachments
fix RemoveEventListener
(3.94 KB, patch)
2007-02-22 00:32 PST
,
Feng Qian
mjs
: review-
Details
Formatted Diff
Diff
test case
(216 bytes, text/html)
2007-02-22 12:04 PST
,
Feng Qian
no flags
Details
revised patch
(5.36 KB, patch)
2007-02-22 13:02 PST
,
Feng Qian
no flags
Details
Formatted Diff
Diff
fixed wrong path names in ChangeLog
(5.36 KB, patch)
2007-02-22 13:11 PST
,
Feng Qian
no flags
Details
Formatted Diff
Diff
revised patch again
(9.06 KB, patch)
2007-02-22 14:06 PST
,
Feng Qian
darin
: review-
Details
Formatted Diff
Diff
revised patch again again
(8.71 KB, patch)
2007-02-22 14:44 PST
,
Feng Qian
mjs
: review-
Details
Formatted Diff
Diff
patch again again again
(12.07 KB, patch)
2007-02-22 19:08 PST
,
Feng Qian
mjs
: review+
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Feng Qian
Comment 1
2007-02-22 00:32:48 PST
Created
attachment 13311
[details]
fix RemoveEventListener I think the problem is in kjs_window.cpp, Window::getJSEventListener, which creates a JSEventListener object if it does not exist. The constructor of JSEventListener makes JSValue GC-protected. In Window::RemoveEventListener and DOMEventTargetNode::RemoveEventListener, both calls getJSEventListener to check if a listener exists. This leaks both JSEventListener and the JavaScript event listener object. I added a new function Window::hasJSEventListener for checking if a JSEventListener exists for a JS event listener object without creating a new one. Before the change, run-safari and visit Gmail, then exist. Safari reports: LEAK: 2102 Node LEAK: 158688 KJS::Node After applying the patch, no message reported.
Maciej Stachowiak
Comment 2
2007-02-22 01:04:26 PST
Comment on
attachment 13311
[details]
fix RemoveEventListener The change itself looks good. Thanks, this will is a really valuable fix! Technicalities: - Needs a ChangeLog entry - Needs a test case - Per the coding style guidelines, the * should go next to the type name, although it is hard to tell from the current surrounding code. r- for now for the technicalities.
Maciej Stachowiak
Comment 3
2007-02-22 01:24:29 PST
May also fix
http://bugs.webkit.org/show_bug.cgi?id=12659
Feng Qian
Comment 4
2007-02-22 12:04:53 PST
Created
attachment 13324
[details]
test case It leaks several objects.
Feng Qian
Comment 5
2007-02-22 13:02:51 PST
Created
attachment 13325
[details]
revised patch Renamed hasJSEventListener to findJSEventListener. Fixed some style issues and added an entry in ChangeLog.
Feng Qian
Comment 6
2007-02-22 13:10:02 PST
(In reply to
comment #3
)
> May also fix
http://bugs.webkit.org/show_bug.cgi?id=12659
>
I cannot find significant number of leaked JS object when visiting both sites even without fixing this bug. It might be fixed by an early patch that clearing helper object properties of window object.
Feng Qian
Comment 7
2007-02-22 13:11:35 PST
Created
attachment 13326
[details]
fixed wrong path names in ChangeLog
Feng Qian
Comment 8
2007-02-22 14:01:27 PST
***
Bug 12853
has been marked as a duplicate of this bug. ***
Feng Qian
Comment 9
2007-02-22 14:06:12 PST
Created
attachment 13327
[details]
revised patch again added findJSUnprotectedEventListener and fixed use in JSXMLHttpRequest.cpp; added a leak counter for EventListeners.
Darin Adler
Comment 10
2007-02-22 14:16:47 PST
Comment on
attachment 13327
[details]
revised patch again Great fix! Is there no way to add a test for this? We really want a test for each bug fix if at all possible. + if (listener) { node->removeEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec)); + } Please don't add braces. Our coding style guidelines call for no braces on a single-line if statement. Also, adding those braces makes the patch longer for no good reason. +JSEventListener *Window::findJSEventListener(JSValue* val, bool html) { Braces that open a function call go on a separate line per our guidelines. The * goes next to the type name as per our style guidelines. + JSObject *object = static_cast<JSObject *>(val); The * goes next to the type name as per our style guidelines. - case Window::RemoveEventListener: + case Window::RemoveEventListener: { if (!window->isSafeScript(exec)) return jsUndefined(); - if (JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1])) + JSEventListener *listener = Window::retrieveActive(exec)->findJSEventListener(args[1]); + if (listener) { if (Document *doc = frame->document()) doc->removeWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec)); + } return jsUndefined(); + } Why the gratuitous style change here? By putting the variable inside the if we avoid the need for braces around the entire case statement. There's no need to tweak the style while fixing this bug; I think it just makes the patch bigger and obscures the point of what you're fixing. + JSEventListener *findJSEventListener(JSValue*, bool html = false); * goes next to the type name. + // JS Object. + JSUnprotectedEventListener *findJSUnprotectedEventListener(JSValue*, bool html = false); Please put a blank lines between the comment and the declaration here as with the other functions.
Feng Qian
Comment 11
2007-02-22 14:29:21 PST
(In reply to
comment #10
)
> (From update of
attachment 13327
[details]
[edit]) > Great fix!
> Thanks for your quick review. Here are some of my arguments:
> Is there no way to add a test for this? We really want a test for each bug fix > if at all possible.
I attached a test case to in the bug report.
http://bugs.webkit.org/attachment.cgi?id=13324&action=view
> > + if (listener) { > node->removeEventListener(args[0]->toString(exec), > listener,args[2]->toBoolean(exec)); > + } > > Please don't add braces. Our coding style guidelines call for no braces on a > single-line if statement. Also, adding those braces makes the patch longer for > no good reason. > > +JSEventListener *Window::findJSEventListener(JSValue* val, bool html) { > > Braces that open a function call go on a separate line per our guidelines. The > * goes next to the type name as per our style guidelines.
I followed local style in the file. The local style also uses 2 spaces for indention.
> > + JSObject *object = static_cast<JSObject *>(val); > > The * goes next to the type name as per our style guidelines. > > - case Window::RemoveEventListener: > + case Window::RemoveEventListener: { > if (!window->isSafeScript(exec)) > return jsUndefined(); > - if (JSEventListener *listener = > Window::retrieveActive(exec)->getJSEventListener(args[1])) > + JSEventListener *listener = > Window::retrieveActive(exec)->findJSEventListener(args[1]); > + if (listener) { > if (Document *doc = frame->document()) > > doc->removeWindowEventListener(AtomicString(args[0]->toString(exec)), listener, > args[2]->toBoolean(exec)); > + } > return jsUndefined(); > + } > > Why the gratuitous style change here? By putting the variable inside the if we > avoid the need for braces around the entire case statement. There's no need to > tweak the style while fixing this bug; I think it just makes the patch bigger > and obscures the point of what you're fixing. > > + JSEventListener *findJSEventListener(JSValue*, bool html = false); > > * goes next to the type name. > > + // JS Object. > + JSUnprotectedEventListener *findJSUnprotectedEventListener(JSValue*, bool > html = false); > > Please put a blank lines between the comment and the declaration here as with > the other functions. >
Feng Qian
Comment 12
2007-02-22 14:44:03 PST
Created
attachment 13328
[details]
revised patch again again In new functions I added, I follow style guide: 4-space indention and * following type name. In existing functions, I follow the local rules.
Maciej Stachowiak
Comment 13
2007-02-22 18:34:38 PST
Comment on
attachment 13328
[details]
revised patch again again The right way to add a test case is to included it in the patch, in the LayoutTests directory. In this case, LayoutTests/fast/events would be the appropriate directory. This is so the person committing doesn't have to do extra work applying the patch. Also: I think the comments on the findJSEventListener and related methods are excessive. Can we get these down to one or two lines instead of having whole paragraphs in the header? Better yet, how about renaming the methods to make behavior more clear from the name? getJSEventListener could be renamed to findOrCreateJSEventListener for instance. r- for lack of test case. Please also consider my feedback about the large comments. We tend to avoid those in WebKit because they can make it harder to read the code. Code-wise though, the patch is fine to land once a test case is added to the patch.
Feng Qian
Comment 14
2007-02-22 19:08:51 PST
Created
attachment 13336
[details]
patch again again again Your comments are well taken.
Maciej Stachowiak
Comment 15
2007-02-22 19:17:05 PST
Comment on
attachment 13336
[details]
patch again again again r=me
Sam Weinig
Comment 16
2007-02-22 20:01:11 PST
Landed in
r19820
.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug