Bug 141736

Summary: [GTK] Crash in debug builds when closing web page after r180214
Product: WebKit Reporter: Michael Catanzaro <mcatanzaro>
Component: WebKitGTKAssignee: Nobody <webkit-unassigned>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: cgarcia, mcatanzaro, svillar
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: PC   
OS: Linux   

Description Michael Catanzaro 2015-02-17 18:59:49 PST
r180214 seems to have introduced a crash when closing epiphany. I need to debug this further but my guess at this point is that in DOMObjectCacheFrameObserver::frameDestroyed, the call to domObjectCacheFrameObservers().remove(frame) causes the destruction of the DOMObjectCacheFrameObserver, which is bad because WebCore::FrameDestructionObserver's destructor calls m_frame->removeDestructionObserver, resulting in WebCore::Frame::m_destructionObservers changing size while it is being iterated through in WebCore::Frame's destructor. That's probably illegal.

#0  0x00007f6f920aa3a7 in WTFCrash ()
    at ../../Source/WTF/wtf/Assertions.cpp:321
No locals.
#1  0x00007f6f97df035f in WTF::HashTableConstIterator<WebCore::FrameDestructionObserver*, WebCore::FrameDestructionObserver*, WTF::IdentityExtractor, WTF::PtrHash<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*> >::checkValidity (this=0x7fff804241d0) at ../../Source/WTF/wtf/HashTable.h:210
        __PRETTY_FUNCTION__ = "void WTF::HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkValidity() const [with Key = WebCore::FrameDestructionObserver*; Value = WebCore::FrameDestructionObserv"...
#2  0x00007f6f97def7e0 in WTF::HashTableConstIterator<WebCore::FrameDestructionObserver*, WebCore::FrameDestructionObserver*, WTF::IdentityExtractor, WTF::PtrHash<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*> >::operator++
    (this=0x7fff804241d0) at ../../Source/WTF/wtf/HashTable.h:177
        __PRETTY_FUNCTION__ = "WTF::HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::const_iterator& WTF::HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator++()"...
#3  0x00007f6f97dee42a in WTF::HashTableConstIteratorAdapter<WTF::HashTable<WebCore::FrameDestructionObserver*, WebCore::FrameDestructionObserver*, WTF::IdentityExtractor, WTF::PtrHash<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*>, WTF::HashTraits<WebCore::FrameDestructionObserver*> >, WebCore::FrameDestructionObserver*>::operator++ (this=0x7fff804241d0)
    at ../../Source/WTF/wtf/HashTable.h:1363
No locals.
#4  0x00007f6f97debe5e in WebCore::Frame::willDetachPage (this=0x7f6f6d7ed000)
    at ../../Source/WebCore/page/Frame.cpp:785
        observer = @0x7f6f6dffe4c8: 0x85ab80
        __for_range = @0x7f6f6d7ed010: {m_impl = {
            static m_maxLoad = <optimized out>, 
            static m_minLoad = <optimized out>, m_table = 0x7f6f6dffe4c0, 
            m_tableSize = 8, m_tableSizeMask = 7, m_keyCount = 2, 
            m_deletedCount = 1, m_iterators = 0x0, 
            m_mutex = std::unique_ptr<std::mutex> containing 0x7a6ee0}}
        __for_begin = {m_impl = {m_position = 0x7f6f6dffe4c8, 
            m_endPosition = 0x7f6f6dffe500, m_table = 0x0, m_next = 0x0, 
            m_previous = 0x0}}
        __for_end = {m_impl = {m_position = 0x7f6f6dffe500, 
            m_endPosition = 0x7f6f6dffe500, m_table = 0x0, m_next = 0x0, 
            m_previous = 0x0}}
#5  0x00007f6f97cac54c in WebCore::FrameLoader::detachFromParent (
    this=0x7f6f6d7ed098) at ../../Source/WebCore/loader/FrameLoader.cpp:2496
        parent = 0x0
        protect = {m_ptr = 0x7f6f6d7ed000}
#6  0x00007f6f971d5eb0 in WebKit::WebPage::close (this=0x7f6f6c012600)
    at ../../Source/WebKit2/WebProcess/WebPage/WebPage.cpp:1037
        isRunningModal = false
#7  0x00007f6f973838b9 in IPC::callMemberFunctionImpl<WebKit::WebPage, void (WebKit::WebPage::*)(), std::tuple<>>(WebKit::WebPage*, void (WebKit::WebPage::*)(), std::tuple<>&&, std::index_sequence<>) (object=0x7f6f6c012600, 
    function=(void (WebKit::WebPage::*)(WebKit::WebPage * const)) 0x7f6f971d5aee <WebKit::WebPage::close()>, 
    args=<unknown type in /home/mcatanzaro/jhbuild/install/lib/libwebkit2gtk-4.0.so.37, CU 0xc7eeee6, DIE 0xc87c1c4>)
    at ../../Source/WebKit2/Platform/IPC/HandleMessage.h:16
No locals.
#8  0x00007f6f9738193e in IPC::callMemberFunction<WebKit::WebPage, void (WebKit::WebPage::*)(), std::tuple<>, std::make_index_sequence<0ul> >(std::tuple<>&&, WebKit::WebPage*, void (WebKit::WebPage::*)()) (
    args=<unknown type in /home/mcatanzaro/jhbuild/install/lib/libwebkit2gtk-4.0.so.37, CU 0xc7eeee6, DIE 0xc875b80>, object=0x7f6f6c012600, 
    function=(void (WebKit::WebPage::*)(WebKit::WebPage * const)) 0x7f6f971d5aee <WebKit::WebPage::close()>)
    at ../../Source/WebKit2/Platform/IPC/HandleMessage.h:22
No locals.
#9  0x00007f6f9737dbd8 in IPC::handleMessage<Messages::WebPage::Close, WebKit::WebPage, void (WebKit::WebPage::*)()> (decoder=..., object=0x7f6f6c012600, 
    function=(void (WebKit::WebPage::*)(WebKit::WebPage * const)) 0x7f6f971d5aee <WebKit::WebPage::close()>)
    at ../../Source/WebKit2/Platform/IPC/HandleMessage.h:92
        __PRETTY_FUNCTION__ = "void IPC::handleMessage(IPC::MessageDecoder&, C*, MF) [with T = Messages::WebPage::Close; C = WebKit::WebPage; MF = void (WebKit::WebPage::*)()]"
        arguments = empty std::tuple
#10 0x00007f6f973780d1 in WebKit::WebPage::didReceiveWebPageMessage (
    this=0x7f6f6c012600, connection=..., decoder=...)
    at DerivedSources/WebKit2/WebPageMessageReceiver.cpp:629
        __PRETTY_FUNCTION__ = "void WebKit::WebPage::didReceiveWebPageMessage(IPC::Connection&, IPC::MessageDecoder&)"
#11 0x00007f6f971e0505 in WebKit::WebPage::didReceiveMessage (
    this=0x7f6f6c012600, connection=..., decoder=...)
    at ../../Source/WebKit2/WebProcess/WebPage/WebPage.cpp:3584
No locals.
#12 0x00007f6f96eb40a6 in IPC::MessageReceiverMap::dispatchMessage (
    this=0x6e5fc0, connection=..., decoder=...)
    at ../../Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp:87
        messageReceiver = 0x7f6f6c012610
        __PRETTY_FUNCTION__ = "bool IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::MessageDecoder&)"
#13 0x00007f6f970abad4 in WebKit::WebProcess::didReceiveMessage (
    this=0x6e5ec0, connection=..., decoder=...)
    at ../../Source/WebKit2/WebProcess/WebProcess.cpp:611
        __PRETTY_FUNCTION__ = "virtual void WebKit::WebProcess::didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&)"
#14 0x00007f6f96ea26c0 in IPC::Connection::dispatchMessage (
    this=0x7f6f6d7fb000, decoder=...)
    at ../../Source/WebKit2/Platform/IPC/Connection.cpp:837
No locals.
#15 0x00007f6f96ea278c in IPC::Connection::dispatchMessage (
    this=0x7f6f6d7fb000, 
    message=std::unique_ptr<IPC::MessageDecoder> containing 0x7f6f6def0180)
    at ../../Source/WebKit2/Platform/IPC/Connection.cpp:860
        oldDidReceiveInvalidMessage = false
#16 0x00007f6f96ea294f in IPC::Connection::dispatchOneMessage (
    this=0x7f6f6d7fb000)
    at ../../Source/WebKit2/Platform/IPC/Connection.cpp:888
        message = std::unique_ptr<IPC::MessageDecoder> containing 0x0
#17 0x00007f6f96eb3419 in WTF::FunctionWrapper<void (IPC::Connection::*)()>::operator() (this=0x7f6f6dfec6c8, c=0x7f6f6d7fb000)
    at ../../Source/WTF/wtf/Functional.h:218
No locals.
#18 0x00007f6f96eb3264 in WTF::BoundFunctionImpl<WTF::FunctionWrapper<void (IPC::Connection::*)()>, void (IPC::Connection*)>::operator()() (
    this=0x7f6f6dfec6b8) at ../../Source/WTF/wtf/Functional.h:496
No locals.
#19 0x00007f6f96eacb77 in WTF::Function<void ()>::operator()() const (
    this=0x7f6f140011d0) at ../../Source/WTF/wtf/Functional.h:704
        __PRETTY_FUNCTION__ = "R WTF::Function<R()>::operator()() const [with R = void]"
#20 0x00007f6f96ea93ac in std::_Function_handler<void (), WTF::Function<void ()> >::_M_invoke(std::_Any_data const&) (__functor=...)
    at /usr/include/c++/4.9.2/functional:2039
No locals.
#21 0x00007f6f96e8b450 in std::function<void ()>::operator()() const (
    this=0x7fff80425e30) at /usr/include/c++/4.9.2/functional:2439
No locals.
#22 0x00007f6f98cc60a9 in WTF::RunLoop::performWork (this=0x7f6f6dff9000)
    at ../../Source/WTF/wtf/RunLoop.cpp:104
        function = {<std::_Maybe_unary_or_binary_function<void>> = {<No data fields>}, <std::_Function_base> = {static _M_max_size = 16, 
            static _M_max_align = 8, _M_functor = {_M_unused = {
                _M_object = 0x7f6f140011d0, _M_const_object = 0x7f6f140011d0, 
                _M_function_pointer = 0x7f6f140011d0, 
                _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7f6f140011d0, this adjustment 140116597139168}, 
              _M_pod_data = "\320\021\000\024o\177\000\000\340\346\377oo\177\000"}, 
            _M_manager = 0x7f6f96ea93ae <std::_Function_base::_Base_manager<WTF::Function<void ()> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation)>}, 
          _M_invoker = 0x7f6f96ea938c <std::_Function_handler<void (), WTF::Function<void ()> >::_M_invoke(std::_Any_data const&)>}
        functionsToHandle = 1
#23 0x00007f6f98cc9908 in WTF::RunLoop::<lambda()>::operator()(void) const (
    __closure=0x7f6f14001e20) at ../../Source/WTF/wtf/gtk/RunLoopGtk.cpp:104
        runLoop = {m_ptr = 0x7f6f6dff9000}
#24 0x00007f6f98cc9e90 in std::_Function_handler<void(), WTF::RunLoop::wakeUp()::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...)
    at /usr/include/c++/4.9.2/functional:2039
No locals.
#25 0x00007f6f96e8b450 in std::function<void ()>::operator()() const (
    this=0x7fff80425f68) at /usr/include/c++/4.9.2/functional:2439
No locals.
#26 0x00007f6f920f2bbf in WTF::GMainLoopSource::voidCallback (
    this=0x7f6f6dfa0dc0)
    at ../../Source/WTF/wtf/gobject/GMainLoopSource.cpp:365
        context = {source = {m_ptr = 0x7f6f14001e40}, cancellable = {
            m_ptr = 0x0}, socketCancellable = {m_ptr = 0x0}, 
          voidCallback = {<std::_Maybe_unary_or_binary_function<void>> = {<No data fields>}, <std::_Function_base> = {static _M_max_size = 16, 
              static _M_max_align = 8, _M_functor = {_M_unused = {
                  _M_object = 0x7f6f14001e20, 
                  _M_const_object = 0x7f6f14001e20, 
                  _M_function_pointer = 0x7f6f14001e20, 
                  _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7f6f14001e20, this adjustment 140117281643823}, 
                _M_pod_data = " \036\000\024o\177\000\000/\235̘o\177\000"}, 
              _M_manager = 0x7f6f98cc9e92 <std::_Function_base::_Base_manager<WTF::RunLoop::wakeUp()::<lambda()> >::_M_manager(std::_Any_data &, const std::_Any_data &, std::_Manager_operation)>}, 
            _M_invoker = 0x7f6f98cc9e70 <std::_Function_handler<void(), WTF::RunLoop::wakeUp()::<lambda()> >::_M_invoke(const std::_Any_data &)>}, 
          boolCallback = {<std::_Maybe_unary_or_binary_function<bool>> = {<No data fields>}, <std::_Function_base> = {static _M_max_size = 16, 
              static _M_max_align = 8, _M_functor = {_M_unused = {
                  _M_object = 0x7f6f6dfa0e48, 
                  _M_const_object = 0x7f6f6dfa0e48, 
                  _M_function_pointer = 0x7f6f6dfa0e48, 
                  _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7f6f6dfa0e48, this adjustment 140116597137616}, 
                _M_pod_data = "H\016\372mo\177\000\000\320\340\377oo\177\000"}, _M_manager = 0x0}, _M_invoker = 0x7f6f6fffe1f0}, 
          socketCallback = {<std::_Maybe_unary_or_binary_function<bool, GIOCondition>> = {<std::unary_function<GIOCondition, bool>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, 
              static _M_max_align = 8, _M_functor = {_M_unused = {
                  _M_object = 0x7f6f6fffe170, 
                  _M_const_object = 0x7f6f6fffe170, 
                  _M_function_pointer = 0x7f6f6fffe170, 
                  _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7f6f6fffe170, this adjustment 140116597137632}, 
                _M_pod_data = "p\341\377oo\177\000\000\340\340\377oo\177\000"}, _M_manager = 0x0}, _M_invoker = 0x7f6f6fffe0f0}, 
          destroyCallback = {<std::_Maybe_unary_or_binary_function<void>> = {<No data fields>}, <std::_Function_base> = {static _M_max_size = 16, 
              static _M_max_align = 8, _M_functor = {_M_unused = {
                  _M_object = 0x7f6f6fffe2c0, 
                  _M_const_object = 0x7f6f6fffe2c0, 
                  _M_function_pointer = 0x7f6f6fffe2c0, 
                  _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7f6f6fffe2c0, this adjustment 140116563562504}, 
                _M_pod_data = "\300\342\377oo\177\000\000\b\220\377mo\177\000"}, _M_manager = 0x0}, _M_invoker = 0x641550}}
#27 0x00007f6f920f32c3 in WTF::GMainLoopSource::voidSourceCallback (
    source=0x7f6f6dfa0dc0)
    at ../../Source/WTF/wtf/gobject/GMainLoopSource.cpp:456
No locals.
#28 0x00007f6f8e19cfe2 in g_idle_dispatch (source=0x7f6f14001e40, 
    callback=0x7f6f920f32a0 <WTF::GMainLoopSource::voidSourceCallback(WTF::GMainLoopSource*)>, user_data=0x7f6f6dfa0dc0) at gmain.c:5392
No locals.
#29 0x00007f6f8e19a656 in g_main_dispatch (context=0x641550) at gmain.c:3122
        dispatch = 0x7f6f8e19cf96 <g_idle_dispatch>
        prev_source = 0x0
        was_in_call = 0
        user_data = 0x7f6f6dfa0dc0
        callback = 0x7f6f920f32a0 <WTF::GMainLoopSource::voidSourceCallback(WTF::GMainLoopSource*)>
        cb_funcs = 0x7f6f8e4a6a00 <g_source_callback_funcs>
        cb_data = 0x7f6f14001ed0
        need_destroy = 0
        source = 0x7f6f14001e40
        current = 0x662110
        i = 0
        __FUNCTION__ = "g_main_dispatch"
#30 0x00007f6f8e19b491 in g_main_context_dispatch (context=0x641550)
    at gmain.c:3737
No locals.
#31 0x00007f6f8e19b676 in g_main_context_iterate (context=0x641550, block=1, 
    dispatch=1, self=0x66b190) at gmain.c:3808
        max_priority = 2147483647
        timeout = 4997
        some_ready = 1
        nfds = 5
        allocated_nfds = 5
        fds = 0x6c3210
#32 0x00007f6f8e19ba9d in g_main_loop_run (loop=0xaa2f20) at gmain.c:4002
        self = 0x66b190
        __FUNCTION__ = "g_main_loop_run"
#33 0x00007f6f98cc9682 in WTF::RunLoop::run ()
    at ../../Source/WTF/wtf/gtk/RunLoopGtk.cpp:59
        mainRunLoop = @0x7f6f6dff9000: {<WTF::FunctionDispatcher> = {<WTF::ThreadSafeRefCounted<WTF::FunctionDispatcher>> = {<WTF::ThreadSafeRefCountedBase> = {m_refCount = {<std::__atomic_base<int>> = {
                    _M_i = 3}, <No data fields>}}, <No data fields>}, 
            _vptr.FunctionDispatcher = 0x7f6f9c485d50 <vtable for WTF::RunLoop+16>}, m_functionQueueLock = {m_mutex = {__data = {__lock = 0, __count = 0, 
                __owner = 0, __nusers = 0, __kind = 512, __spins = 0, 
                __elision = 0, __list = {__prev = 0x0, __next = 0x0}}, 
              __size = '\000' <repeats 17 times>, "\002", '\000' <repeats 21 times>, __align = 0}}, m_functionQueue = {m_start = 6, m_end = 7, 
            m_buffer = {<WTF::VectorBufferBase<std::function<void()> >> = {
                m_buffer = 0x7f6f6d7f8000, m_capacity = 21, 
                m_size = 0}, <No data fields>}, m_iterators = 0x0}, 
          m_runLoopContext = {m_ptr = 0x641550}, 
          m_runLoopMainLoops = {<WTF::VectorBuffer<WTF::GRefPtr<_GMainLoop>, 0ul>> = {<WTF::VectorBufferBase<WTF::GRefPtr<_GMainLoop> >> = {
                m_buffer = 0x7f6f6dffc180, m_capacity = 16, 
                m_size = 1}, <No data fields>}, <No data fields>}}
        innermostLoop = 0xaa2f20
        nestedMainLoop = 0x7ec6b0
#34 0x00007f6f972f90c4 in WebKit::ChildProcessMain<WebKit::WebProcess, WebKit::WebProcessMain> (argc=2, argv=0x7fff80426358)
    at ../../Source/WebKit2/Shared/unix/ChildProcessMain.h:61
        childMain = {<WebKit::ChildProcessMainBase> = {
            _vptr.ChildProcessMainBase = 0x7f6f9c2eed30 <vtable for WebKit::WebProcessMain+16>, m_parameters = {uiProcessName = {m_impl = {m_ptr = 0x0}}, 
              clientIdentifier = {m_impl = {m_ptr = 0x0}}, 
              connectionIdentifier = 26, extraInitializationData = {m_impl = {
                  static m_maxLoad = <optimized out>, 
                  static m_minLoad = <optimized out>, m_table = 0x0, 
                  m_tableSize = 0, m_tableSizeMask = 0, m_keyCount = 0, 
                  m_deletedCount = 0, m_iterators = 0x0, 
                  m_mutex = std::unique_ptr<std::mutex> containing 0x61b8e0}}}}, <No data fields>}
#35 0x00007f6f972f8f2f in WebKit::WebProcessMainUnix (argc=2, 
    argv=0x7fff80426358)
    at ../../Source/WebKit2/WebProcess/gtk/WebProcessMainGtk.cpp:77
No locals.
#36 0x0000000000400c0a in main (argc=2, argv=0x7fff80426358)
    at ../../Source/WebKit2/WebProcess/EntryPoint/unix/WebProcessMain.cpp:44
No locals.
Comment 1 Carlos Garcia Campos 2015-02-18 00:53:18 PST
(In reply to comment #0)
> r180214 seems to have introduced a crash when closing epiphany. I need to
> debug this further but my guess at this point is that in
> DOMObjectCacheFrameObserver::frameDestroyed, the call to
> domObjectCacheFrameObservers().remove(frame) causes the destruction of the
> DOMObjectCacheFrameObserver, which is bad because
> WebCore::FrameDestructionObserver's destructor calls
> m_frame->removeDestructionObserver, resulting in
> WebCore::Frame::m_destructionObservers changing size while it is being
> iterated through in WebCore::Frame's destructor. That's probably illegal.
> 

The crash happens when Frame::willDetachPage() iterates the observers, so at that point frameDestroyed() hasn't been called at all, it's called in ~Frame. When the frame is destroyed we call the parent FrameDestructionObserver::frameDestroyed() that sets m_frame to nullptr, so when the DOMObjectCacheFrameObserver is deleted, the destructor doesn't call m_frame->removeDestructionObserver() because m_frame is already nullptr. That's why things happen in that order, and the reason why we save the m_frame pointer before calling FrameDestructionObserver::frameDestroyed(). So, unless something really weird is happening, it must be something else.
Comment 2 Michael Catanzaro 2015-02-18 05:07:49 PST
You are right. I think I somehow switched from looking at the iteration over the observer list in Frame::willDetatchPage() to the one in the destructor and never looked back. Silly...
Comment 3 Michael Catanzaro 2015-03-21 12:17:43 PDT
I am not seeing this crash anymore, and it used to happen 100%, so I think it's obsolete.
Comment 4 Michael Catanzaro 2015-05-01 17:10:36 PDT

*** This bug has been marked as a duplicate of bug 144508 ***