Bug 27397

Summary: [V8] V8IsolatedWorld keeps a handle to a disposed context
Product: WebKit Reporter: Matt Perry <mpcomplete>
Component: WebCore JavaScriptAssignee: Adam Barth <abarth>
Status: RESOLVED FIXED    
Severity: Normal CC: abarth, ager, dglazkov, levin
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: OS X 10.5   
Attachments:
Description Flags
patch
none
Fix weak handle issue
none
test extension
none
patch levin: review+

Matt Perry
Reported 2009-07-17 16:25:15 PDT
This line in V8IsolatedWorld::evaluate: context.Dispose(); should probably be removed. The handle has already been made weak - disposing it makes the handle invalid, causing crashes when it is used later.
Attachments
patch (1.19 KB, patch)
2009-07-17 17:07 PDT, Adam Barth
no flags
Fix weak handle issue (1.31 KB, patch)
2009-07-17 17:19 PDT, Adam Barth
no flags
test extension (59.73 KB, application/octet-stream)
2009-07-20 16:34 PDT, Matt Perry
no flags
patch (1.54 KB, patch)
2009-07-21 02:28 PDT, Adam Barth
levin: review+
Adam Barth
Comment 1 2009-07-17 17:01:10 PDT
Where is |context| made weak? |m_context| is made weak, but isn't that a separate handle? I agree that that line of code can be removed. The intent is to hold a reference to the context for the duration of that function, which we can do without that line.
Adam Barth
Comment 2 2009-07-17 17:07:19 PDT
Matt Perry
Comment 3 2009-07-17 17:08:28 PDT
(In reply to comment #1) > Where is |context| made weak? |m_context| is made weak, but isn't that a > separate handle? My understanding is that m_context and context share the reference to the object. If you want m_context to be a different reference, you need to do: m_context = v8::Persistent<v8::Context>::New(context);
Adam Barth
Comment 4 2009-07-17 17:13:25 PDT
(In reply to comment #3) > My understanding is that m_context and context share the reference to the > object. If you want m_context to be a different reference, you need to do: > m_context = v8::Persistent<v8::Context>::New(context); Ah. I wish the V8 API had better docs. Do you know of any?
Adam Barth
Comment 5 2009-07-17 17:19:02 PDT
Comment on attachment 32989 [details] patch Silly bzt. Not obsolete.
Adam Barth
Comment 6 2009-07-17 17:19:51 PDT
Created attachment 32991 [details] Fix weak handle issue
Matt Perry
Comment 7 2009-07-17 18:00:42 PDT
(In reply to comment #4) > Ah. I wish the V8 API had better docs. Do you know of any? No.. in fact, I tried to search for information to back up my claim, and couldn't find anything definitive. The closest I could come was the comments regarding the "storage cell" on the v8::Persistent constructor and Dispose() methods in the v8 header. So take what I'm saying with a grain of salt :).
Mads Ager
Comment 8 2009-07-19 23:39:18 PDT
Each call to Persistent::New creates a new cell that needs to be disposed by a call to Dispose on a handle that refers to that cell (either this handle or a copy of it created by passing the handle by value). Context::New does a call to Persistent::New under the hood, so anything that you get from a call to Context::New eventually has to be disposed. So, in evaluate, you call createNewContext which returns a newly allocated persistent handle that has to be disposed at some point. Your weak reference callback needs to Dispose the handle on which it is called to actually free the object on the JavaScript side. Once you make that change, I think either of these patches should be fine (but not both): In patch one, you pass on ownership of the allocated persistent to the isolated world which makes the handle weak. Once the handle gets the callback it will be disposed (make sure to dispose the handle in the callback). In that case, it is correct that you should not call Dispose on the handle in the evaluate method since you have passed ownership to the isolated world. In patch two, you keep ownership of the allocated handle and let the isolated world allocate a new handle. In that case, you have to dispose both of the allocated handles when you are done with them. The isolated world handle will be disposed in the weak callback and you need to dispose the other handle as well at the end of evaluate.
Adam Barth
Comment 9 2009-07-19 23:51:38 PDT
We have to manually dispose of persistent handles? I presume we leak the cell if we don't. Hum... We probably have that bug a lot. Why can't the handle destructor dispose of the cell?
Mads Ager
Comment 10 2009-07-19 23:55:22 PDT
Because handles are passed by value and therefore many handles can point to the same cell. We should not have that bug a lot. When objects are removed from the DOMMap tables in the weak handle callbacks, the persistent handle is disposed.
Adam Barth
Comment 11 2009-07-19 23:58:47 PDT
Ok. I'll audit the bindings layer for this issue. We'll also probably want to create some kind of OwnPersistentHandle helper class to avoid leaking the cells. I'm going to cancel these reviews while I figure out the best thing to do in this case. Thanks for explaining how this stuff works.
Adam Barth
Comment 12 2009-07-20 09:58:44 PDT
Comment on attachment 32991 [details] Fix weak handle issue I believe this is the one we want.
Eric Seidel (no email)
Comment 13 2009-07-20 15:23:28 PDT
Comment on attachment 32991 [details] Fix weak handle issue r- for lack of test, or explanation why no test is possible.
Adam Barth
Comment 14 2009-07-20 16:03:19 PDT
Matt, do you have a test case that prompted you to file this bug?
Matt Perry
Comment 15 2009-07-20 16:34:27 PDT
Created attachment 33123 [details] test extension (In reply to comment #14) > Matt, do you have a test case that prompted you to file this bug? I think the following pieces are key: - Run chrome with extensions enabled, and install/load an extension(*) that has a content script. - Navigate to the page that uses the content script. - Chrome must call into the script later via the chrome extension bindings (or maybe a DOM event listener would work here). * Attached is the extension I used to repro it. Install it with a trunk build of chrome and navigate to google.com. You might need to refresh a few times to repro. (works in --single-process)
Adam Barth
Comment 16 2009-07-20 16:53:48 PDT
Thanks Matt. If we can trigger this with a DOM event, then we can test it using a LayoutTest. From your description, I think that will work. I'll investigate tonight.
Matt Perry
Comment 17 2009-07-20 17:07:45 PDT
(In reply to comment #16) > Thanks Matt. If we can trigger this with a DOM event, then we can test it > using a LayoutTest. From your description, I think that will work. I'll > investigate tonight. Note that I haven't tested it with a DOM event. I was just theorizing that they might share a common code path.
Adam Barth
Comment 18 2009-07-20 20:51:00 PDT
Comment on attachment 32991 [details] Fix weak handle issue Re-nominating this patch because I can't seem to reproduce the issue with a DOM event handler. I'm not sure this is testable without the rest of the extension system.
Mads Ager
Comment 19 2009-07-21 01:29:45 PDT
This looks good to me if the weak reference callback disposes the persistent handle. If the weak reference callback does not dispose the handle there will be a call to Persistent::New with no matching Dispose which will lead to a memory leak.
Adam Barth
Comment 20 2009-07-21 02:22:06 PDT
Comment on attachment 32991 [details] Fix weak handle issue The weak callback doesn't currently. I'll spin up a new version that does.
Adam Barth
Comment 21 2009-07-21 02:28:01 PDT
David Levin
Comment 22 2009-07-21 09:52:38 PDT
Comment on attachment 33164 [details] patch Mads Ager says this looks good and he know this a lot better than I do. No style issues. So I'll rubber stamp it based on his review.
Adam Barth
Comment 23 2009-07-21 10:09:37 PDT
Committing to http://svn.webkit.org/repository/webkit/trunk ... M WebCore/ChangeLog M WebCore/bindings/v8/V8IsolatedWorld.cpp Committed r46177 M WebCore/ChangeLog M WebCore/bindings/v8/V8IsolatedWorld.cpp r46177 = ae70d4b8a715c5b701c40e3fc6ed526d23bc32da (trunk) No changes between current HEAD and refs/remotes/trunk Resetting to the latest refs/remotes/trunk http://trac.webkit.org/changeset/46177
Note You need to log in before you can comment on or make changes to this bug.