Closed
Bug 1194627
Opened 10 years ago
Closed 10 years ago
Fix intermittent LSan-detected leak, bug 1166041
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
mozilla43
| Tracking | Status | |
|---|---|---|
| firefox40 | --- | unaffected |
| firefox41 | --- | fixed |
| firefox42 | --- | fixed |
| firefox43 | --- | fixed |
| firefox-esr38 | --- | unaffected |
People
(Reporter: jandem, Assigned: jandem)
References
Details
(Keywords: memory-leak, Whiteboard: [MemShrink])
Attachments
(3 files)
|
15.84 KB,
patch
|
gkw
:
feedback+
|
Details | Diff | Splinter Review |
|
455 bytes,
text/plain
|
Details | |
|
1.80 KB,
patch
|
bhackett1024
:
review+
ritu
:
approval-mozilla-aurora+
ritu
:
approval-mozilla-beta+
|
Details | Diff | Splinter Review |
Filing a separate bug because bug 1166041 is pretty hard to read with all the Treeherder comments.
| Assignee | ||
Comment 1•10 years ago
|
||
This patch tracks allocation and deallocation of slots and other object buffers. It fails very intermittently on Try, I think/hope it's the same issue as the one LSan detects. Would be great if we could get a reliable shell testcase.
I'm interested in any assertion failures that include: allocatedObjectBuffers_
Fuzzers might find false positives (problems with this patch) though.
Should apply to m-c revision 4e883591bb5d
Attachment #8647946 -
Flags: feedback?(gary)
Attachment #8647946 -
Flags: feedback?(choller)
| Assignee | ||
Comment 2•10 years ago
|
||
Phew, after many Try builds and staring at log files I finally understand the problem. Here's what happens:
(1) We have a JSOP_NEWOBJECT (object literal) where we allocate ~20 objects with external/dyamic slots. These are put in the ObjectGroup's PreliminaryObjectArray.
(2) One of these objects dies, is swept and removed from the PreliminaryObjectArray.
(3) We allocate another object that takes its place in the PreliminaryObjectArray.
(4) We give the group an unboxed layout. This makes all objects in the PreliminaryObjectArray UnboxedPlainObjects.
(5) Now the object swept in (2) is finalized in the background, however the isNative() check incorrectly returns false for this object because we changed the group's clasp while giving it an unboxed layout. This means we don't free its slots/elements.
So this is basically a race: the main thread has to give the group an unboxed class before the object is finalized. When that happens, we don't free its slots/elements.
| Assignee | ||
Comment 3•10 years ago
|
||
Here's a test that fails with --no-ggc and the allocation tracking patch I attached previously, on OS X 32-bit:
$ dist/bin/js --no-ggc test.js
Assertion failure: allocatedObjectBuffers_ == 0, at js/src/vm/Runtime.cpp:462
This is very fragile though; it probably won't fail on other platforms due to timing/threading/allocation differences.
| Assignee | ||
Comment 4•10 years ago
|
||
Comment on attachment 8647946 [details] [diff] [review]
Track allocations
Cancelling feedback because I found the problem. Thanks!
Attachment #8647946 -
Flags: feedback?(gary)
Attachment #8647946 -
Flags: feedback?(choller)
| Assignee | ||
Comment 5•10 years ago
|
||
Brian, the simplest fix I can think of is to js_delete the slots/elements in PreliminaryObjectArray::sweep(). Does that sound okay to you? Is there a better way?
I'll see if this fixes it.
Flags: needinfo?(bhackett1024)
Comment 6•10 years ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #5)
> Brian, the simplest fix I can think of is to js_delete the slots/elements in
> PreliminaryObjectArray::sweep(). Does that sound okay to you? Is there a
> better way?
Yes, that looks like the best way to handle this. Thanks so much for tracking this down!
Flags: needinfo?(bhackett1024)
| Assignee | ||
Comment 7•10 years ago
|
||
Hm this fix is wrong for unboxed arrays though, JSObject::finalize will call the UnboxedArrayObject finalize hook on a NativeObject.
I wonder if it'd be simpler to have sweep() call setGroup with a stable PlainObject/ArrayObject ObjectGroup..
Comment 8•10 years ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #7)
> Hm this fix is wrong for unboxed arrays though, JSObject::finalize will call
> the UnboxedArrayObject finalize hook on a NativeObject.
>
> I wonder if it'd be simpler to have sweep() call setGroup with a stable
> PlainObject/ArrayObject ObjectGroup..
Hmm, good point. I don't think you need a PlainObject or ArrayObject group specifically, but any group such that clasp->isNative() and the clasp won't change in the future (this would eliminate the race entirely too, which is nice). I think the group pointer of the compartment's global should suffice, though I can't tell if it is guaranteed to be non-NULL when we hit PreliminaryObjectGroup::sweep. If the global has been cleared though then the compartment is dead and the preliminary objects will never be analyzed anyways.
| Assignee | ||
Comment 9•10 years ago
|
||
(In reply to Brian Hackett (:bhackett) from comment #8)
> I think the group pointer of the compartment's global should
> suffice, though I can't tell if it is guaranteed to be non-NULL when we hit
> PreliminaryObjectGroup::sweep. If the global has been cleared though then
> the compartment is dead and the preliminary objects will never be analyzed
> anyways.
Makes sense. I was thinking of a global `static const` struct that has a Class* pointer at offset 0, but using the global's group might be nicer.
We have to make sure clasp->finalize is nullptr though for the global, but we can just assert that.
Comment 10•10 years ago
|
||
Comment on attachment 8647946 [details] [diff] [review]
Track allocations
In any case, this patch didn't throw up anything on 1 machine overnight. feedback+ for posterity.
Attachment #8647946 -
Flags: feedback+
| Assignee | ||
Comment 11•10 years ago
|
||
We also need to make sure PreliminaryObjectArray::sweep is always called before JSObject::finalize. Not sure if that's guaranteed with background finalization of objects, will look into this later.
| Assignee | ||
Comment 12•10 years ago
|
||
The plan to use the global's group didn't work because the global has a finalize hook in the browser.
This patch uses the Object.prototype group. All green and it fixes the leak:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=7f0c039534f7
Attachment #8648381 -
Flags: review?(bhackett1024)
Comment 13•10 years ago
|
||
My hero!
status-firefox40:
--- → unaffected
status-firefox41:
--- → affected
status-firefox42:
--- → affected
status-firefox43:
--- → affected
status-firefox-esr38:
--- → unaffected
Updated•10 years ago
|
Attachment #8648381 -
Flags: review?(bhackett1024) → review+
Comment 14•10 years ago
|
||
Comment 15•10 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
Comment 16•10 years ago
|
||
Please nominate this for Aurora/Beta approval when you get a chance.
Flags: needinfo?(jdemooij)
| Assignee | ||
Comment 17•10 years ago
|
||
Comment on attachment 8648381 [details] [diff] [review]
Patch
Approval Request Comment
[Feature/regressing bug #]: Bug 1162199.
[User impact if declined]: Memory leaks.
[Describe test coverage new/current, TreeHerder]: Known to fix this leak on Treeherder.
[Risks and why]: Low risk.
[String/UUID change made/needed]: None.
Flags: needinfo?(jdemooij)
Attachment #8648381 -
Flags: approval-mozilla-beta?
Attachment #8648381 -
Flags: approval-mozilla-aurora?
Comment 18•10 years ago
|
||
Comment on attachment 8648381 [details] [diff] [review]
Patch
Memleaks are bad, let's uplift to Aurora and Beta.
Attachment #8648381 -
Flags: approval-mozilla-beta?
Attachment #8648381 -
Flags: approval-mozilla-beta+
Attachment #8648381 -
Flags: approval-mozilla-aurora?
Attachment #8648381 -
Flags: approval-mozilla-aurora+
You need to log in
before you can comment on or make changes to this bug.
Description
•