Closed Bug 1439470 Opened 7 years ago Closed 7 years ago

Crash in RedBlackTree<T>::Remove at rb.h:520, rb.h:462

Categories

(Core :: Memory Allocator, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla60
Tracking Status
firefox60 --- fixed

People

(Reporter: glandium, Assigned: glandium)

References

Details

Attachments

(3 files)

There are other classes of crashes in RedBlackTree<T>::Remove, which I'm sure existed before bug 1412722 (most of them are double-free of huge allocations), but there are at least two kinds that I could find that are related to something I spotted while translating the current rb.h code to rust: https://crash-stats.mozilla.com/report/index/26ceeaa3-db9f-4641-a46b-dc68d0180220 https://crash-stats.mozilla.com/report/index/c59942ce-cede-4d8b-8e1a-b25b50180219 Those are null derefs caused by the absence of the sentinel.
(In reply to Mike Hommey [:glandium] from comment #0) > There are other classes of crashes in RedBlackTree<T>::Remove, which I'm > sure existed before bug 1412722 (most of them are double-free of huge > allocations) I failed to mention: those are bug 1405062. > We additionally ensure that nothing in the calling code will be trying > to change the color or left/right pointers on the sentinel, which is an > extra safe net compared to the code before bug 1412722. Another advantage of this change is that it should separate those crash signatures from those related to double-free, although I'm also going to file another bug to make those separate too.
Comment on attachment 8952276 [details] Bug 1439470 - Turn TreeNode into a smart pointer-like type. https://reviewboard.mozilla.org/r/221518/#review227314 Code analysis found 1 defect in this patch: - 1 defect found by clang-tidy You can run this analysis locally with: - `./mach static-analysis check path/to/file.cpp` (C/C++) If you see a problem in this automated review, please report it here: http://bit.ly/2y9N9Vx ::: memory/build/rb.h:194 (Diff revision 1) > - Trait::GetTreeNode(this).SetColor(aColor); > + Trait::GetTreeNode(mNode).SetColor(aColor); > } > + > + T* Get() { return mNode; } > + > + operator bool() { return mNode; } Error: Bad implicit conversion operator for 'treenode' [clang-tidy: mozilla-explicit-operator-bool]
Comment on attachment 8952276 [details] Bug 1439470 - Turn TreeNode into a smart pointer-like type. https://reviewboard.mozilla.org/r/221518/#review227326 ::: memory/build/rb.h:194 (Diff revision 2) > - Trait::GetTreeNode(this).SetColor(aColor); > + Trait::GetTreeNode(mNode).SetColor(aColor); > } > + > + T* Get() { return mNode; } > + > + MOZ_IMPLICIT operator bool() { return mNode; } `return !!mNode` is clearer?
Attachment #8952276 - Flags: review?(n.nethercote) → review+
Comment on attachment 8952277 [details] Bug 1439470 - Turn TreeNode(nullptr) into a "virtual" sentinel. https://reviewboard.mozilla.org/r/221520/#review227328 ::: memory/build/rb.h:192 (Diff revision 2) > } > > - NodeColor Color() { return Trait::GetTreeNode(mNode).Color(); } > + NodeColor Color() > + { > + return mNode ? Trait::GetTreeNode(mNode).Color() : NodeColor::Black; > + } I don't see any comments in rb.h about sentinels. It feels like there should be some...
Attachment #8952277 - Flags: review?(n.nethercote) → review+
Comment on attachment 8952277 [details] Bug 1439470 - Turn TreeNode(nullptr) into a "virtual" sentinel. https://reviewboard.mozilla.org/r/221520/#review227332 ::: memory/build/rb.h:167 (Diff revision 2) > { > mNode = aOther.mNode; > return *this; > } > > - TreeNode Left() { return TreeNode(Trait::GetTreeNode(mNode).Left()); } > + TreeNode Left() Comments about how Left() and Right() work would probably also be useful.
Comment on attachment 8952278 [details] Bug 1439470 - Remove some now unnecessary checks. https://reviewboard.mozilla.org/r/221522/#review227330 ::: commit-message-17af0:1 (Diff revision 2) > +Bug 1439470 - Remove some not unnecessary checks. r?njn Remove the "not"?
Attachment #8952278 - Flags: review?(n.nethercote) → review+
(In reply to Nicholas Nethercote [:njn] from comment #12) > Comment on attachment 8952278 [details] > Bug 1439470 - Remove some not unnecessary checks. > > https://reviewboard.mozilla.org/r/221522/#review227330 > > ::: commit-message-17af0:1 > (Diff revision 2) > > +Bug 1439470 - Remove some not unnecessary checks. r?njn > > Remove the "not"? Hah, it was meant to be spelled "now".
Comment on attachment 8952277 [details] Bug 1439470 - Turn TreeNode(nullptr) into a "virtual" sentinel. Does this satisfy your comments?
Attachment #8952277 - Flags: review+ → review?(n.nethercote)
Comment on attachment 8952277 [details] Bug 1439470 - Turn TreeNode(nullptr) into a "virtual" sentinel. https://reviewboard.mozilla.org/r/221520/#review227342 Looks good, thank you.
Attachment #8952277 - Flags: review?(n.nethercote) → review+
Pushed by mh@glandium.org: https://hg.mozilla.org/integration/autoland/rev/f95559ae3134 Turn TreeNode into a smart pointer-like type. r=njn https://hg.mozilla.org/integration/autoland/rev/cf9d00862149 Turn TreeNode(nullptr) into a "virtual" sentinel. r=njn https://hg.mozilla.org/integration/autoland/rev/c43ee00c3e6b Remove some now unnecessary checks. r=njn
Thank you GCC for creating stupid code for constexpr constructors: 0000000000406170 <_GLOBAL__sub_I_Unified_cpp_memory_build0.cpp>: 406170: 55 push %rbp 406171: 48 c7 05 fc e4 22 00 movq $0x0,0x22e4fc(%rip) # 634678 <_ZL7gArenas+0x38> 406178: 00 00 00 00 40617c: 48 c7 05 f9 e4 22 00 movq $0x0,0x22e4f9(%rip) # 634680 <_ZL7gArenas+0x40> 406183: 00 00 00 00 406187: 48 89 e5 mov %rsp,%rbp 40618a: 5d pop %rbp 40618b: c3 retq 40618c: 0f 1f 40 00 nopl 0x0(%rax) Best part? _ZL7gArenas is in .bss: 0000000000634640 l O .bss 0000000000000048 _ZL7gArenas The funny part? The static initializer above runs *after* malloc_init_hard, so those movq's overwrite gArenas.mArenas.mRoot, which, at that time, contains mDefaultArena. So when iterating the arenas in the atfork handler after a fork(), the default arena is not forcefully unlocked, and if the default arena lock happens to be held before the fork, the child process ends up dead-locked when something else tries to get the default arena lock. I thought adding a constexpr (non-default) constructor on RedBlackTree might help, but it doesn't. Removing the constexpr constructor on TreeNode doesn't work either because of the other constructor that takes a T* that needs to exist, so I'm afraid the only workaround to GCC's stupidity here is to turn mRoot into a T*.
Flags: needinfo?(mh+mozilla)
Adding a constexpr constructor to RedBlackTree *and* ArenaCollection makes the static initializer go away.
Well, MSVC can also do funny things with constexpr: https://bugs.chromium.org/p/chromium/issues/detail?id=660967
Attachment #8952276 - Flags: review+ → review?(n.nethercote)
Comment on attachment 8952276 [details] Bug 1439470 - Turn TreeNode into a smart pointer-like type. https://reviewboard.mozilla.org/r/221518/#review228104 ::: memory/build/rb.h:204 (Diff revisions 2 - 4) > T* mNode; > }; > > private: > - TreeNode mRoot; > + // Ideally we'd use a TreeNode for mRoot, but we need RedBlackTree to stay > + // a POD to avoid a static initializer for gArenas. "a POD type"?
Attachment #8952276 - Flags: review?(n.nethercote) → review+
Pushed by mh@glandium.org: https://hg.mozilla.org/integration/autoland/rev/f56735818e28 Turn TreeNode into a smart pointer-like type. r=njn https://hg.mozilla.org/integration/autoland/rev/31f9d7d3f703 Turn TreeNode(nullptr) into a "virtual" sentinel. r=njn https://hg.mozilla.org/integration/autoland/rev/9665d7248cc5 Remove some now unnecessary checks. r=njn
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla60
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: