Closed Bug 1217531 Opened 9 years ago Closed 6 years ago

Leak with createShadowRoot, adoptNode

Categories

(Core :: DOM: Core & HTML, defect, P3)

defect

Tracking

()

RESOLVED WORKSFORME
Tracking Status
firefox44 --- affected

People

(Reporter: jruderman, Unassigned, Mentored)

References

Details

(Keywords: memory-leak, testcase, Whiteboard: [tw-dom] btpp-active)

Attachments

(7 files, 5 obsolete files)

Attached file testcase (obsolete) —
trace-refcnt reports leaked nsGlobalWindow, nsDocument, etc. (Using a Mac debug build with XPCOM_MEM_LEAK_LOG=2)
The test case failed at line 13. TypeError: div.createShadowRoot is not a function var shadowroot = element.createShadowRoot();
(In reply to Shawn Huang [:shawnjohnjr] from comment #1) > The test case failed at line 13. > TypeError: div.createShadowRoot is not a function > > var shadowroot = element.createShadowRoot(); oh. I did not know i have to enable dom.webcomponents.enabled flag.
Whiteboard: [tw-dom] → [tw-dom] btpp-active
https://bugzilla.mozilla.org/show_bug.cgi?id=957109#c27 I guess this issue is related to this comment. "IsInDoc() handling of ShadowRoot need to be fixed, but it isn't clear to me how it should work. Currently it certainly is wrong since document.createElement("div").createShadowRoot() creates a thing which is in document, although the shadow host isn't in document."
Attachment #8743151 - Attachment description: bug1217531.patch (WIP) → bug1217531 test
I don't know why running this, the output seems strange. env XPCOM_MEM_LOG_CLASSES=nsGlobalWindow XPCOM_MEM_REFCNT_LOG=/home/shawnjohnjr/refcnt.txt ./mach mochitest dom/base/test/test_bug1217531.html
$ python find_roots.py /tmp/cc-edges.6252.1461153426.log nsGlobalWindow Parsing /tmp/cc-edges.6252.1461153426.log. Done loading graph. 0x7f6042534800 [nsGlobalWindow # 2147483652 outer http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] Root 0x7f6042534800 is a ref counted object with 1 unknown edge(s). known edges: 0x7f6042535000 [nsGlobalWindow # 2147483653 inner about:blank] --[mOuterWindow]--> 0x7f6042534800 0x7f604165fc00 [nsGlobalWindow # 2147483655 inner http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mOuterWindow]--> 0x7f6042534800 0x7f60424a4c00 [nsGlobalWindow # 2147483654 inner about:blank] --[mOuterWindow]--> 0x7f6042534800 0x7f604251a7e0 [nsJSContext] --[mGlobalObjectRef]--> 0x7f6042534800
Is it correct to check nsGlobalWindow using find_roots.py for this case? I followed the instruction[1], and run tools/rb/find_leakers.py, but I can't get the result. The refcnt report seems missing symbols. [1]https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Refcount_tracing_and_balancing
Flags: needinfo?(wchen)
refcnt.txt looks like: <nsGlobalWindow> 0x7f48856be800 1 AddRef 1 [thread 0x7f48a699c4a0] #01: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x175a323] #02: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x176f404] #03: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2e5f9bb] #04: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2e3f89e] #05: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2e3faa0] #06: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2abe7f1] #07: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2e4c5b4] #08: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2eba583] #09: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2ebac88] #10: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x2ebb0ff] #11: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x30c324e] #12: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x3113d97] #13: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x3114468] #14: XRE_main[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/libxul.so +0x311472e] #15: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/firefox +0x56f8] #16: ???[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/firefox +0x4ec5] #17: __libc_start_main[/lib/x86_64-linux-gnu/libc.so.6 +0x20a40] #18: _start[/home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dist/bin/firefox +0x4fe9] #19: ??? (???:???) tools/rb/find_leakers.py ~/refcnt.txt Traceback (most recent call last): File "tools/rb/find_leakers.py", line 99, in <module> main() File "tools/rb/find_leakers.py", line 93, in main process_log(log_lines) File "tools/rb/find_leakers.py", line 46, in process_log count,) = log_line.strip('\r\n').split(' ') ValueError: too many values to unpack
Maybe I misunderstood how to use this tool. Now I found something interesting. find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa190953380 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa18fb79400 [nsGlobalWindow # 2147483689 outer http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mContext]--> 0x7fa190953380 [nsJSContext] Root 0x7fa18fb79400 is a ref counted object with 1 unknown edge(s). known edges: 0x7fa190953380 [nsJSContext] --[mGlobalObjectRef]--> 0x7fa18fb79400 0x7fa1909c7000 [nsGlobalWindow # 2147483692 inner http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mOuterWindow]--> 0x7fa18fb79400 find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa1909c7000 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa198a17000 [nsDocument normal (xhtml) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mScriptGlobalObject]--> 0x7fa1909c7000 [nsGlobalWindow # 2147483692 inner http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] Root 0x7fa198a17000 is a ref counted object with 6 unknown edge(s). known edges: 0x7fa19053a2e0 [JS Object (HTMLDocument)] --[UnwrapDOMObject(obj)]--> 0x7fa198a17000 0x7fa18fb79400 [nsGlobalWindow # 2147483689 outer http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mDoc]--> 0x7fa198a17000 0x7fa190a9f000 [nsDocument normal (xhtml) http://mochi.test:8888/tests?autorun=1&consoleLevel=INFO&manifestFile=tests.json&dumpOutputDirectory=%2Ftmp] --[mSubDocuments entry->mSubDocument]--> 0x7fa198a17000 0x7fa1927e0b80 [nsXBLDocumentInfo] --[mDocument]--> 0x7fa198a17000 0x7fa18f2600a0 [nsNodeInfoManager] --[mDocument]--> 0x7fa198a17000 0x7fa18efe3160 [AnimationTimeline] --[mDocument]--> 0x7fa198a17000 0x7fa1909c7000 [nsGlobalWindow # 2147483692 inner http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mDoc]--> 0x7fa198a17000 0x7fa191f3ffb0 [DOMImplementation] --[mOwner]--> 0x7fa198a17000
I listed all ShadowRoot. > 0x7fa190325b00 ShadowRoot > 0x7fa190426240 ShadowRoot > 0x7fa1906c0b20 ShadowRoot > 0x7fa1925d8e40 ShadowRoot > 0x7fa19088ad80 ShadowRoot > 0x7fa193952180 ShadowRoot find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa190325b00 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa190325b00 [JS Object (Function)] Root 0x7fa190325b00 is a marked GC object. find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa190426240 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa190426240 [JS Object (Function)] Root 0x7fa190426240 is a marked GC object. find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa1906c0b20 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa1906c0b20 [JS Object (Function)] Root 0x7fa1906c0b20 is a marked GC object. python find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa1925d8e40 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa18fb41140 [nsNodeInfoManager] --[mDocument]--> 0x7fa18fb47000 [nsDocument normal (xhtml) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mExpandoAndGeneration.expando]--> 0x7fa191e4b1a0 [JS Object (Object)] --[global]--> 0x7fa1925d62e0 [JS Object (Window)] --[ShadowRoot, protoAndIfaceCache[i]]--> 0x7fa1925d8e40 [JS Object (Function)] Root 0x7fa18fb41140 is a ref counted object with 1 unknown edge(s). find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa19088ad80 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa1922af080 [nsXBLDocumentInfo] --[mDocument]--> 0x7fa1927c9000 [nsDocument normal (xhtml) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mExpandoAndGeneration.expando]--> 0x7fa1908de400 [JS Object (Object)] --[global]--> 0x7fa1925d67e0 [JS Object (Window)] --[ShadowRoot, protoAndIfaceCache[i]]--> 0x7fa19088ad80 [JS Object (Function)] Root 0x7fa1922af080 is a ref counted object with 1 unknown edge(s). python find_roots.py /tmp/cc-edges.8152.1461210326.log 0x7fa193952180 Parsing /tmp/cc-edges.8152.1461210326.log. Done loading graph. 0x7fa18f25f200 [nsNodeInfoManager] --[mDocument]--> 0x7fa195dff000 [nsDocument normal (xhtml) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[Preserved wrapper]--> 0x7fa1925e8400 [JS Object (HTMLDocument)] --[global]--> 0x7fa1925d6560 [JS Object (Window)] --[ShadowRoot, protoAndIfaceCache[i]]--> 0x7fa193952180 [JS Object (Function)] Root 0x7fa18f25f200 is a ref counted object with 1 unknown edge(s).
I should minimize memory, so i will upload the log again.
Attached file cc&gc-edges.zip
The GC & CC logs got after setting following envs and close the browser when the test finishes: export MOZ_CC_LOG_DIRECTORY=... export MOZ_CC_LOG_SHUTDOWN=1 export MOZ_CC_RUN_DURING_SHUTDOWN=1 Now there are something that we're interested: 0x7f6b5fc5e080 [rc=2] FragmentOrElement (xhtml) div (orphan) about:blank > 0x7f6b5fc4c780 mNodeInfo > 0x7f6b63a0cba0 mSlots->mXBLBinding > 0x7f6b6076cf20 mSlots->mShadowRoot 0x7f6b6076cf20 [rc=3] FragmentOrElement ([none]) #document-fragment (orphan) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html > 0x7f6b5fc4c600 mNodeInfo > 0x7f6b6076cf20 mSlots->mContainingShadow > 0x7f6b5fc5e080 mPoolHost > 0x7f6b63a0cba0 mAssociatedBinding Attachment 8743676 [details] was captured from about:memory "save verbose GC & CC logs", not sure why it does not contain the edges above though.
Attachment #8743676 - Attachment is obsolete: true
clear ni, since i have more information to continue this problem.
Flags: needinfo?(wchen)
Hmm. Maybe I get cc dump before shutdowning so i can't see orphan keyword in the original cc dump.
0x7f0e5cddce50 [rc=2] FragmentOrElement (xhtml) div (orphan) about:blank python find_roots.py ~/cc-edges-log/cc-edges.22430.log 0x7f0e5cddce50 <<<<FragmentOrElement (xhtml) div (orphan) about:blank>>>> Parsing /home/shawnjohnjr/cc-edges-log/cc-edges.22430.log. Done loading graph. 0x7f0e5cddce50 [FragmentOrElement (xhtml) div (orphan) about:blank] Root 0x7f0e5cddce50 is a ref counted object with 1 unknown edge(s). known edges: 0x7f0e5cd77ad0 [FragmentOrElement ([none]) #document-fragment (orphan) http://mochi.test:8888/tests/dom/base/test/test_bug1217531.html] --[mPoolHost]--> 0x7f0e5cddce50 Checking FragmentOrElement now.
#0 mozilla::dom::FragmentOrElement::SetXBLBinding (this=0x7f40b2ff0350, aBinding=0x0, aOldBindingManager=0x7f40bdb6ace0) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/FragmentOrElement.cpp:1017 #1 0x00007f40e55bdb01 in nsBindingManager::RemovedFromDocumentInternal (this=0x7f40bdb6ace0, aContent=aContent@entry=0x7f40b2ff0350, aOldDocument=aOldDocument@entry= 0x7f40b95f8000, aDestructorHandling=aDestructorHandling@entry=nsBindingManager::eRunDtor) at /home/shawnjohnjr/code/mozilla-inbound/dom/xbl/nsBindingManager.cpp:216 #2 0x00007f40e46645be in nsBindingManager::RemovedFromDocument (aDestructorHandling=nsBindingManager::eRunDtor, aOldDocument=0x7f40b95f8000, aContent=0x7f40b2ff0350, this=<optimized out>) at /home/shawnjohnjr/code/mozilla-inbound/dom/xbl/nsBindingManager.h:74 #3 mozilla::dom::FragmentOrElement::DestroyContent (this=0x7f40b2ff0350) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/FragmentOrElement.cpp:1187 #4 0x00007f40e46645ff in mozilla::dom::FragmentOrElement::DestroyContent (this=0x7f40b96d8b00) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/FragmentOrElement.cpp:1193 #5 0x00007f40e46e3edb in nsDocument::Destroy (this=0x7f40b95f8000) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/nsDocument.cpp:8929 #6 0x00007f40e5963999 in nsDocumentViewer::Destroy (this=0x7f40b95fb1a0) at /home/shawnjohnjr/code/mozilla-inbound/layout/base/nsDocumentViewer.cpp:1641 #7 0x00007f40e5cd6ba0 in nsDocShell::Destroy (this=0x7f40b9656800) at /home/shawnjohnjr/code/mozilla-inbound/docshell/base/nsDocShell.cpp:5712 #8 0x00007f40e46e591b in nsFrameLoader::DestroyDocShell (this=0x7f40b96a4080) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/nsFrameLoader.cpp:1576
If we remove the line "otherDoc.adoptNode(div)", "FragmentOrElement::SetXBLBinding" will be called. But if we call "otherDoc.adoptNode(div)" in the test case, we never set SetXBLBinding(nullptr).
In case you haven't found it yet, tools/rb/fix_linux_stack.py and fix_macosx_stack.py can be run on a refcount log in order to symbolize it, depending on the OS you are on. It is faster to run it on the result of make-tree.pl.
(In reply to Andrew McCreight [:mccr8] from comment #25) > In case you haven't found it yet, tools/rb/fix_linux_stack.py and > fix_macosx_stack.py can be run on a refcount log in order to symbolize it, > depending on the OS you are on. It is faster to run it on the result of > make-tree.pl. oh! Now I see. Thanks a lot.
No progress on this bug for a week is due to i'm working on storage last week, I will continue on this bug this week.
So when we don't execute |adoptNode()| in the test case, |nsWebShellWindow::RequestWindowClose| will trigger to set FragmentOrElement::SetXBLBinding to nullptr. Without calling adoptNode() in the test case. aBinding set to 0x0 Breakpoint 2, mozilla::dom::FragmentOrElement::SetXBLBinding (this=0x7f5b4bf79ee0, aBinding=0x0, aOldBindingManager=0x7f5b4bf03460) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/FragmentOrElement.cpp:1018 1018 if (aOldBindingManager) { ........ With calling adoptNode() in the test case, I can only see SetXBLBinding been set after CreateShadowRoot. #0 mozilla::dom::FragmentOrElement::SetXBLBinding (this=0x7f49d7ff4350, aBinding=0x7f49d7ff6290, aOldBindingManager=0x0) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/FragmentOrElement.cpp:1018 #1 0x00007f4a09721336 in mozilla::dom::Element::CreateShadowRoot (this=0x7f49d7ff4350, aError=...) at /home/shawnjohnjr/code/mozilla-inbound/dom/base/Element.cpp:1063 #2 0x00007f4a09ea6c4e in mozilla::dom::ElementBinding::createShadowRoot (cx=0x7f49da0ee800, obj=..., self=<optimized out>, args=...) at /home/shawnjohnjr/code/mozilla-inbound/obj-x86_64-pc-linux-gnu/dom/bindings/ElementBinding.cpp:3189 #3 0x00007f4a09f95626 in mozilla::dom::GenericBindingMethod (cx=cx@entry=0x7f49da0ee800, argc=<optimized out>, vp=<optimized out>) at /home/shawnjohnjr/code/mozilla-inbound/dom/bindings/BindingUtils.cpp:2778 #4 0x00007f4a0bbba771 in js::CallJSNative (cx=cx@entry=0x7f49da0ee800, native=0x7f4a09f954cd <mozilla::dom::GenericBindingMethod(JSContext*, unsigned int, JS::Value*)>, args=...) at /home/shawnjohnjr/code/mozilla-inbound/js/src/jscntxtinlines.h:235 #5 0x00007f4a0bbb2e63 in js::InternalCallOrConstruct (cx=0x7f49da0ee800, args=..., construct=js::NO_CONSTRUCT) at /home/shawnjohnjr/code/mozilla-inbound/js/src/vm/Interpreter.cpp:480 #6 0x00007f4a0bba49e0 in js::CallFromStack (args=..., cx=<optimized out>) at /home/shawnjohnjr/code/mozilla-inbound/js/src/vm/Interpreter.cpp:531 #7 Interpret (cx=0x7f49da0ee800, state=...) at /home/shawnjohnjr/code/mozilla-inbound/js/src/vm/Interpreter.cpp:2831 #8 0x00007f4a0bbb2c3b in js::RunScript (cx=cx@entry=0x7f49da0ee800, state=...) at /home/shawnjohnjr/code/mozilla-inbound/js/src/vm/Interpreter.cpp:426 #9 0x00007f4a0bbb2f06 in js::InternalCallOrConstruct (cx=cx@entry=0x7f49da0ee800, args=..., construct=construct@entry=js::NO_CONSTRUCT) at /home/shawnjohnjr/code/mozilla-inbound/js/src/vm/Interpreter.cpp:498
See Also: → 1076784
Ting, thanks for the hint. So removing |!GetShadowRoot()| can enforce RemoveFromBindingManagerRunnable be executed. if (document) { // Notify XBL- & nsIAnonymousContentCreator-generated // anonymous content that the document is changing. // Unlike XBL, bindings for web components shadow DOM // do not get uninstalled. - if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && !GetShadowRoot()) { + if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { nsContentUtils::AddScriptRunner( new RemoveFromBindingManagerRunnable(document->BindingManager(), this, document)); }
I guess we have shadow root and XBL binding both on the same node, and since we don't remove binding from BindingManager, XBL binding leaks. Maybe unknown edge is called "[via binding manager] mBoundContentSet entry". https://dxr.mozilla.org/mozilla-central/source/dom/xbl/nsBindingManager.cpp#1006
Hi William, It looks like we keep the XBL binding on purpose in bug 1076784. So I'm wondering if we really want keep XBL Binding here. Do you have any suggestion? https://dxr.mozilla.org/mozilla-central/source/dom/base/Element.cpp#1813
Flags: needinfo?(wchen)
(In reply to Shawn Huang [:shawnjohnjr] from comment #32) > Hi William, > It looks like we keep the XBL binding on purpose in bug 1076784. So I'm > wondering if we really want keep XBL Binding here. Do you have any > suggestion? > > https://dxr.mozilla.org/mozilla-central/source/dom/base/Element.cpp#1813 ShadowRoot use XBL bindings to implement its behavior so we should always have a XBL binding when there is a ShadowRoot. In the code you reference, we do still want to keep the binding in the shadow root case. That code is there because XBL uninstalls bindings when you remove the bound node from the document. The shadow DOM spec does not say to do this.
Flags: needinfo?(wchen)
See Also: → 1416296
Priority: -- → P3

Since createShadownRoot was removed, is this bug still valid?

Flags: needinfo?(emilio)

we need to see if it repros with attachShadow. But Shadow DOM and XBL were decoupled long ago, so I suspect it won't repro.

Flags: needinfo?(emilio)
Attached file updated testcase
Attachment #8677599 - Attachment is obsolete: true
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → WORKSFORME
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: