Bug 179062

Summary: http/tests/workers/service/ServiceWorkerGlobalScope-properties.html is flaky
Product: WebKit Reporter: Chris Dumez <cdumez>
Component: WebCore Misc.Assignee: Chris Dumez <cdumez>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: beidson, ggaren, jlewis3, youennf
Priority: P2    
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=179067

Chris Dumez
Reported 2017-10-31 10:40:36 PDT
http/tests/workers/service/ServiceWorkerGlobalScope-properties.html is a flaky timeout and sometimes crashes: Process: com.apple.WebKit.WebContent.Development [82928] Path: /Volumes/VOLUME/*/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Development Identifier: com.apple.WebKit.WebContent Version: 605+ (605.1.3+) Code Type: X86-64 (Native) Parent Process: ??? [1] Responsible: WebKitTestRunner [82844] User ID: 501 Date/Time: 2017-10-31 08:38:03.516 -0700 OS Version: Mac OS X 10.11.6 (15G1510) Report Version: 11 Anonymous UUID: 672D1B3C-38BC-D2F3-E02E-5DA86382E04A Time Awake Since Boot: 510000 seconds System Integrity Protection: enabled Crashed Thread: 0 Dispatch queue: com.apple.main-thread Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x00000000bbadbeef Exception Note: EXC_CORPSE_NOTIFY VM Regions Near 0xbbadbeef: --> __TEXT 0000000100feb000-0000000100fee000 [ 12K] r-x/rwx SM=COW /Volumes/VOLUME/*/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Development Application Specific Information: CRASHING TEST: /workers/service/ServiceWorkerGlobalScope-properties.html Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 com.apple.JavaScriptCore 0x0000000114268be7 WTFCrash + 39 (Assertions.cpp:270) 1 com.apple.WebCore 0x0000000106d081d8 WebCore::JSEventListener::jsFunction(WebCore::ScriptExecutionContext&) const + 424 (JSEventListener.h:128) 2 com.apple.WebCore 0x0000000106d04e3d WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event&) + 205 (JSEventListener.cpp:97) 3 com.apple.WebCore 0x0000000107254b6e WebCore::EventTarget::fireEventListeners(WebCore::Event&, WTF::Vector<WTF::RefPtr<WebCore::RegisteredEventListener>, 1ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>) + 974 (EventTarget.cpp:298) 4 com.apple.WebCore 0x0000000107251f36 WebCore::EventTarget::fireEventListeners(WebCore::Event&) + 326 (EventTarget.cpp:238) 5 com.apple.WebCore 0x0000000107254769 WebCore::EventTarget::dispatchEvent(WebCore::Event&) + 233 (EventTarget.cpp:195) 6 com.apple.WebCore 0x0000000108591c80 WebCore::SWClientConnection::postMessageToServiceWorkerClient(unsigned long long, WTF::Ref<WebCore::SerializedScriptValue>&&, unsigned long long, WTF::String const&) + 624 (SWClientConnection.cpp:137) 7 com.apple.WebKit 0x0000000101c73cb5 WebKit::WebSWClientConnection::postMessageToServiceWorkerClient(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&) + 101 (WebSWClientConnection.cpp:102) 8 com.apple.WebKit 0x0000000101c7a717 void IPC::callMemberFunctionImpl<WebKit::WebSWClientConnection, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&), std::__1::tuple<unsigned long long, IPC::DataReference, unsigned long long, WTF::String>, 0ul, 1ul, 2ul, 3ul>(WebKit::WebSWClientConnection*, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&), std::__1::tuple<unsigned long long, IPC::DataReference, unsigned long long, WTF::String>&&, std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul>) + 327 (HandleMessage.h:41) 9 com.apple.WebKit 0x0000000101c7a338 void IPC::callMemberFunction<WebKit::WebSWClientConnection, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&), std::__1::tuple<unsigned long long, IPC::DataReference, unsigned long long, WTF::String>, std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul> >(std::__1::tuple<unsigned long long, IPC::DataReference, unsigned long long, WTF::String>&&, WebKit::WebSWClientConnection*, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&)) + 88 (HandleMessage.h:47) 10 com.apple.WebKit 0x0000000101c7866b void IPC::handleMessage<Messages::WebSWClientConnection::PostMessageToServiceWorkerClient, WebKit::WebSWClientConnection, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&)>(IPC::Decoder&, WebKit::WebSWClientConnection*, void (WebKit::WebSWClientConnection::*)(unsigned long long, IPC::DataReference const&, unsigned long long, WTF::String const&)) + 347 (HandleMessage.h:127) 11 com.apple.WebKit 0x0000000101c77da2 WebKit::WebSWClientConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 770 (WebSWClientConnectionMessageReceiver.cpp:68) 12 com.apple.WebKit 0x0000000101c8fbaf WebKit::WebToStorageProcessConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 319 (WebToStorageProcessConnection.cpp:70) 13 com.apple.WebKit 0x000000010113d393 IPC::Connection::dispatchMessage(IPC::Decoder&) + 51 (Connection.cpp:902) 14 com.apple.WebKit 0x0000000101134651 IPC::Connection::dispatchMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >) + 721 (Connection.cpp:930) 15 com.apple.WebKit 0x000000010113d99f IPC::Connection::dispatchOneMessage() + 1535 (Connection.cpp:959) 16 com.apple.WebKit 0x00000001011449cd IPC::Connection::enqueueIncomingMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >)::$_14::operator()() + 29 (Connection.cpp:896) 17 com.apple.WebKit 0x000000010114491c WTF::Function<void ()>::CallableWrapper<IPC::Connection::enqueueIncomingMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >)::$_14>::call() + 28 (Function.h:101) 18 com.apple.JavaScriptCore 0x00000001142a6aee WTF::Function<void ()>::operator()() const + 142 (Function.h:56) 19 com.apple.JavaScriptCore 0x00000001142c706b WTF::RunLoop::performWork() + 219 (RunLoop.cpp:107) 20 com.apple.JavaScriptCore 0x00000001142c7954 WTF::RunLoop::performWork(void*) + 36 (RunLoopCF.cpp:38) 21 com.apple.CoreFoundation 0x00007fff95b497e1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 22 com.apple.CoreFoundation 0x00007fff95b28f0c __CFRunLoopDoSources0 + 556 23 com.apple.CoreFoundation 0x00007fff95b2842f __CFRunLoopRun + 927 24 com.apple.CoreFoundation 0x00007fff95b27e28 CFRunLoopRunSpecific + 296 25 com.apple.HIToolbox 0x00007fff8a4a1935 RunCurrentEventLoopInMode + 235 26 com.apple.HIToolbox 0x00007fff8a4a176f ReceiveNextEventCommon + 432 27 com.apple.HIToolbox 0x00007fff8a4a15af _BlockUntilNextEventMatchingListInModeWithFilter + 71 28 com.apple.AppKit 0x00007fff8b0d4df6 _DPSNextEvent + 1067 29 com.apple.AppKit 0x00007fff8b0d4226 -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454 30 com.apple.AppKit 0x00007fff8b0c8d80 -[NSApplication run] + 682 31 com.apple.AppKit 0x00007fff8b092368 NSApplicationMain + 1176 32 libxpc.dylib 0x00007fff97ce6194 _xpc_objc_main + 795 33 libxpc.dylib 0x00007fff97ce4bbe xpc_main + 494 34 com.apple.WebKit.WebContent 0x0000000100fecfdd main + 1197 35 libdyld.dylib 0x00007fff947915ad start + 1
Attachments
Chris Dumez
Comment 1 2017-10-31 12:39:21 PDT
The timeouts / crashes seem to go away with the fix for Bug 179067. I'll investigate why.
Chris Dumez
Comment 2 2017-10-31 12:42:39 PDT
(In reply to Chris Dumez from comment #1) > The timeouts / crashes seem to go away with the fix for Bug 179067. I'll > investigate why. The assertion that was hit in JSEventListener::jsFunction() is: // Verify that we have a valid wrapper protecting our function from // garbage collection. That is except for when we're not in the normal // world and can have zombie m_jsFunctions. ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); So this seems to indicate that the JSEventListener object's wrapper has been collected too early. Normally, such collection is prevented by JSEventTarget's visitor: void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor) { wrapped().visitJSEventListeners(visitor); } JSServiceWorkerContainer subclasses JSEventTargets and should therefore use this visiting code.
Chris Dumez
Comment 3 2017-10-31 12:43:28 PDT
(In reply to Chris Dumez from comment #2) > (In reply to Chris Dumez from comment #1) > > The timeouts / crashes seem to go away with the fix for Bug 179067. I'll > > investigate why. > > The assertion that was hit in JSEventListener::jsFunction() is: > // Verify that we have a valid wrapper protecting our function from > // garbage collection. That is except for when we're not in the normal > // world and can have zombie m_jsFunctions. > ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); > > So this seems to indicate that the JSEventListener object's wrapper has been > collected too early. > > Normally, such collection is prevented by JSEventTarget's visitor: > void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor) > { > wrapped().visitJSEventListeners(visitor); > } > > JSServiceWorkerContainer subclasses JSEventTargets and should therefore use > this visiting code. void EventTarget::visitJSEventListeners() is implemented like so: void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor) { EventTargetData* data = eventTargetDataConcurrently(); if (!data) return; auto locker = holdLock(data->eventListenerMap.lock()); EventListenerIterator iterator(&data->eventListenerMap); while (auto* listener = iterator.nextListener()) listener->visitJSFunction(visitor); }
Chris Dumez
Comment 4 2017-10-31 12:46:57 PDT
(In reply to Chris Dumez from comment #3) > (In reply to Chris Dumez from comment #2) > > (In reply to Chris Dumez from comment #1) > > > The timeouts / crashes seem to go away with the fix for Bug 179067. I'll > > > investigate why. > > > > The assertion that was hit in JSEventListener::jsFunction() is: > > // Verify that we have a valid wrapper protecting our function from > > // garbage collection. That is except for when we're not in the normal > > // world and can have zombie m_jsFunctions. > > ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); > > > > So this seems to indicate that the JSEventListener object's wrapper has been > > collected too early. > > > > Normally, such collection is prevented by JSEventTarget's visitor: > > void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor) > > { > > wrapped().visitJSEventListeners(visitor); > > } > > > > JSServiceWorkerContainer subclasses JSEventTargets and should therefore use > > this visiting code. > > void EventTarget::visitJSEventListeners() is implemented like so: > > void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor) > { > EventTargetData* data = eventTargetDataConcurrently(); > if (!data) > return; > > auto locker = holdLock(data->eventListenerMap.lock()); > EventListenerIterator iterator(&data->eventListenerMap); > while (auto* listener = iterator.nextListener()) > listener->visitJSFunction(visitor); > } My bet is that the JSServiceWorkerContainer wrapper gets collected and therefore stops marking its event listeners. However, the ServiceWorkerContainer object is still alive is still tries to fire events. Since event listeners are no longer marked, they may already be collected by the time we try to fire the event.
Chris Dumez
Comment 5 2017-10-31 12:48:22 PDT
(In reply to Chris Dumez from comment #4) > (In reply to Chris Dumez from comment #3) > > (In reply to Chris Dumez from comment #2) > > > (In reply to Chris Dumez from comment #1) > > > > The timeouts / crashes seem to go away with the fix for Bug 179067. I'll > > > > investigate why. > > > > > > The assertion that was hit in JSEventListener::jsFunction() is: > > > // Verify that we have a valid wrapper protecting our function from > > > // garbage collection. That is except for when we're not in the normal > > > // world and can have zombie m_jsFunctions. > > > ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); > > > > > > So this seems to indicate that the JSEventListener object's wrapper has been > > > collected too early. > > > > > > Normally, such collection is prevented by JSEventTarget's visitor: > > > void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor) > > > { > > > wrapped().visitJSEventListeners(visitor); > > > } > > > > > > JSServiceWorkerContainer subclasses JSEventTargets and should therefore use > > > this visiting code. > > > > void EventTarget::visitJSEventListeners() is implemented like so: > > > > void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor) > > { > > EventTargetData* data = eventTargetDataConcurrently(); > > if (!data) > > return; > > > > auto locker = holdLock(data->eventListenerMap.lock()); > > EventListenerIterator iterator(&data->eventListenerMap); > > while (auto* listener = iterator.nextListener()) > > listener->visitJSFunction(visitor); > > } > > My bet is that the JSServiceWorkerContainer wrapper gets collected and > therefore stops marking its event listeners. However, the > ServiceWorkerContainer object is still alive is still tries to fire events. > Since event listeners are no longer marked, they may already be collected by > the time we try to fire the event. If so, it would make sense that Bug 179067 fixes the issue since it makes sure the JSServiceWorkerContainer wrapper does not get garbage collected until its implementation object (owned by Navigator) is destroyed.
Chris Dumez
Comment 6 2017-10-31 13:38:18 PDT
*** This bug has been marked as a duplicate of bug 179067 ***
Note You need to log in before you can comment on or make changes to this bug.