Closed
Bug 1087799
Opened 11 years ago
Closed 11 years ago
Handle cycle collector reentrance better
Categories
(Core :: XPCOM, defect)
Core
XPCOM
Tracking
()
RESOLVED
FIXED
mozilla36
People
(Reporter: mccr8, Assigned: mccr8)
References
Details
(Keywords: sec-audit)
Attachments
(3 files)
|
1.48 KB,
patch
|
smaug
:
review+
|
Details | Diff | Splinter Review |
|
2.27 KB,
patch
|
smaug
:
review+
|
Details | Diff | Splinter Review |
|
4.95 KB,
patch
|
smaug
:
review+
|
Details | Diff | Splinter Review |
For some reason, this has started happening a lot on TBPL, but the stack looks familiar.
What appears to be happening is this:
- We're in the middle of an incremental CC.
- We decide to GC.
-- Thus, we need to finish the incremental CC. Eventually, run Unlink().
--- This runs Promise::cycleCollection::Unlink(), which runs random JS.
---- This triggers a new GC.
----- We're still in the middle of an ICC, so finish the current ICC.
------ We detect reentrance, so we return immediately.
------ The assertion fires because we have not finished the CC.
I think this is sort of okay right now, because we never touch JS in Unlink, but it is kind of getting into a sketchier situation with bug 1052793, because then we store pointers to zones. Though maybe if we're careful that will be okay... I'm not quite sure of the security implications, so I'm hiding it for now.
| Assignee | ||
Comment 1•11 years ago
|
||
One possible safer solution would be to have the CC root |whiteNodes|, and implement some kind of trace hook that scans everything looking for JS. It would be a little slow, but hopefully this isn't too common. I'm not really sure how that would work for entire JS zones, but I guess we could root all globals in the zone, because that's all we really look at.
| Assignee | ||
Updated•11 years ago
|
Assignee: nobody → continuation
Comment 2•11 years ago
|
||
>--- This runs Promise::cycleCollection::Unlink(), which runs random JS.
Note that we're working on stopping that insanity.
| Assignee | ||
Comment 3•11 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #2)
> Note that we're working on stopping that insanity.
Being able to just ban GC entirely during Unlink() would make Terrence happy. :)
| Assignee | ||
Comment 4•11 years ago
|
||
I looked at this, and I'm pretty sure we're not touching GC objects after we might GC. However, there are some improvements we can make to enforce this more thoroughly.
Group: core-security
| Assignee | ||
Comment 5•11 years ago
|
||
If an Unlink() method ends up running JS, it can cause a GC, which will make us reenter the CC,
which will not do anything because we're already in a CC. Therefore, FinishAnyCurrentCollection()
won't finish the CC. This is safe because the CC only touches things it actually holds alive via
the Root() method.
Attachment #8511296 -
Flags: review?(bugs)
| Assignee | ||
Comment 6•11 years ago
|
||
Attachment #8511297 -
Flags: review?(bugs)
| Assignee | ||
Comment 7•11 years ago
|
||
Root() does not actually root JS things, so if some other class's Unlink() method ends
up calling the GC, whiteNodes will end up containing dead pointers. (This is safe right
now because the Unlink and Unroot methods do not do anything to JS things.) It is less
error prone to simply never store those pointers.
Also, add some asserts to enforce that we never call any of the white-object methods
for JS things.
Attachment #8511298 -
Flags: review?(bugs)
| Assignee | ||
Comment 8•11 years ago
|
||
try run: https://tbpl.mozilla.org/?tree=Try&rev=571af010f313
This try run had a stricter version that nulled out mPointers for things in the graph that we didn't add to whiteNodes, but that seems like overkill.
Should probably dupe bug 1062012 forward.
| Assignee | ||
Comment 11•11 years ago
|
||
(In reply to Kyle Huey [:khuey] (khuey@mozilla.com) from comment #9)
> Should probably dupe bug 1062012 forward.
Ah, thanks, I knew there was another bug floating around somewhere.
Comment 12•11 years ago
|
||
Comment on attachment 8511296 [details] [diff] [review]
part 1 - Loosen the invariant in nsCycleCollector::FinishAnyCurrentCollection().
A bit odd setup, but should work.
Attachment #8511296 -
Flags: review?(bugs) → review+
Updated•11 years ago
|
Attachment #8511297 -
Flags: review?(bugs) → review+
Comment 13•11 years ago
|
||
Comment on attachment 8511298 [details] [diff] [review]
part 3 - Do not include any JS things in the list of white nodes.
Oh, this should speed up unlink a bit.
Attachment #8511298 -
Flags: review?(bugs) → review+
| Assignee | ||
Comment 15•11 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #13)
> Oh, this should speed up unlink a bit.
You'd think so, but when I tried this before I couldn't measure any speedup.
| Assignee | ||
Comment 16•11 years ago
|
||
Thanks for the fast reviews!
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/1a2afa35face
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/80ddb4e48db5
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/1cf5fe2afc94
Comment 17•11 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/1a2afa35face
https://hg.mozilla.org/mozilla-central/rev/80ddb4e48db5
https://hg.mozilla.org/mozilla-central/rev/1cf5fe2afc94
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla36
You need to log in
before you can comment on or make changes to this bug.
Description
•