[Webkit-unassigned] [Bug 175852] New: Race condition in StartWebThread causing crash
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Aug 22 14:22:02 PDT 2017
https://bugs.webkit.org/show_bug.cgi?id=175852
Bug ID: 175852
Summary: Race condition in StartWebThread causing crash
Product: WebKit
Version: Other
Hardware: iPhone / iPad
OS: iOS 10.3
Status: NEW
Severity: Major
Priority: P2
Component: WebKit API
Assignee: webkit-unassigned at lists.webkit.org
Reporter: nham at fb.com
We have been seeing an increasing number of crashes in the Facebook app due to a race condition in StartWebThread. The crash involves a race between the main thread and the web thread.
The main thread crashes in this RELEASE_ASSERT in ThreadIdentifierData:
https://opensource.apple.com/source/WTF/WTF-7603.1.30.1.33/wtf/ThreadIdentifierDataPthreads.cpp.auto.html (line 78)
The main thread's stack is:
Thread #0 Crashed:
0 JavaScriptCore 0x1882aabf8 WTF::ThreadIdentifierData::initialize(unsigned int) + 72
1 JavaScriptCore 0x1882a9188 WTF::currentThread() + 48
2 JavaScriptCore 0x1882a9188 WTF::currentThread() + 48
3 JavaScriptCore 0x1882aac04 WTF::initializeApplicationUIThreadIdentifier() + 8
4 WebCore 0x188f76bec StartWebThread() + 504
5 libsystem_pthread.dylib 0x18348f418 __pthread_once_handler + 76
6 libsystem_platform.dylib 0x183484a44 _os_once + 48
7 libsystem_pthread.dylib 0x18348c2fc pthread_once + 64
8 WebKitLegacy 0x18a15ba54 +[WebView(WebPrivate) enableWebThread] + 268
9 WebKitLegacy 0x18a15b68c WebKitInitialize + 68
10 UIKit 0x18a781dd0 ___UIApplicationLoadWebKit_block_invoke + 212
11 libdispatch.dylib 0x18328299c _dispatch_client_callout + 12
12 libdispatch.dylib 0x1832836c8 dispatch_once_f + 52
13 libdispatch.dylib 0x18328299c _dispatch_client_callout + 12
14 libdispatch.dylib 0x1832937a4 _dispatch_barrier_sync_f_slow_invoke + 300
15 libdispatch.dylib 0x18328299c _dispatch_client_callout + 12
16 libdispatch.dylib 0x1832875e4 _dispatch_main_queue_callback_4CF + 992
17 CoreFoundation 0x1843790c4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
18 CoreFoundation 0x184376ce0 __CFRunLoopRun + 1568
19 CoreFoundation 0x1842a6da0 CFRunLoopRunSpecific + 420
20 GraphicsServices 0x185d11070 GSEventRunModal + 96
21 UIKit 0x18a561c98 UIApplicationMain + 204
22 Facebook 0x1000b5738 FBGenericMain (FBGenericMain.m:224)
23 Facebook 0x1000b5240 main (main.m:150)
24 libdyld.dylib 0x1832b5598 start + 0
This RELEASE_ASSERT fires if the pthread TSD key hasn't yet been created. The TSD key is created by WTF::initializeThreading, which is called by JSC::initializeThreading. So basically, the crash occurs because the MT called WTF::ThreadIdentifierData::initialize before another thread finished calling WTF::initializeThreading.
The thread that's responsible for calling WTF::initializeThreading is the WebThread (which is forked off by StartWebThread). The WebThread has this call stack in the crash:
Thread #63:
0 libsystem_kernel.dylib 0x1833c4f60 __psynch_rw_wrlock + 8
1 libsystem_pthread.dylib 0x18348b5c8 _pthread_rwlock_lock + 464
2 libobjc.A.dylib 0x182e35764 rwlock_tt<false>::write() + 100
3 libobjc.A.dylib 0x182e2ebc4 _class_getNonMetaClass + 36
4 libobjc.A.dylib 0x182e354ac lookUpImpOrForward + 220
5 libobjc.A.dylib 0x182e40474 _objc_msgSend_uncached + 52
6 libobjc.A.dylib 0x182e2d414 CALLING_SOME_+initialize_METHOD + 20
7 libobjc.A.dylib 0x182e2d680 _class_initialize + 608
8 libobjc.A.dylib 0x182e354b0 lookUpImpOrForward + 224
9 libobjc.A.dylib 0x182e40474 _objc_msgSend_uncached + 52
10 JavaScriptCore 0x1882a9958 WTF::initializeMainThreadPlatform() + 24
11 libsystem_pthread.dylib 0x18348f418 __pthread_once_handler + 76
12 libsystem_platform.dylib 0x183484a44 _os_once + 48
13 libsystem_pthread.dylib 0x18348c2fc pthread_once + 64
14 WebCore 0x188f78b94 RunWebThread(void*) + 32
15 libsystem_pthread.dylib 0x18348d688 _pthread_body + 236
16 libsystem_pthread.dylib 0x18348d598 _pthread_start + 280
17 libsystem_pthread.dylib 0x18348acb0 thread_start + 0
If you look at the code, the WebThread is stuck two lines *before* the call to JSC::initializeThreading (which is what calls WTF::initializeThreading)--it's executing WTF::initializeMainThreadPlatform:
https://opensource.apple.com/source/WebCore/WebCore-7603.1.30.1.33/platform/ios/wak/WebCoreThread.mm.auto.html (line 653)
In theory, there is some synchronization in the existing code that should prevent this from happening. In pseudo-code, the synchronization code looks like this:
RunWebThread: (running on the web thread)
JSC::initializeThreading()
// other init...
pthread_mutex_lock(&lock)
pthread_cond_signal(&cond, &lock)
pthread_mutex_unlock(&lock)
StartWebThread: (running on the main thread)
pthread_lock(&lock)
pthread_cond_wait(&cond, &lock)
pthread_unlock(&lock)
WTF::initializeApplicationUIThreadIdentifier() // calls code which eventually asserts
However, this synchronization code is buggy because pthread_cond_wait is allowed to spuriously wake up, and pthread_cond_wait is only called once. It is very easy to demonstrate that spurious wakeups exist with pthread condition variables, e.g. here is a simple test program: https://gist.github.com/bnham/f2ca3430a7c4f6f714a918b62702125e
The fix is to add a boolean flag variable and to check whether that boolean variable is set while calling pthread_cond_wait in a loop, i.e. textbook usage of Mesa condition variables.
A possible mitigation for affected apps is to call some JSC API that eventually calls JSC::initializeThreading early on in app initialization.
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20170822/c8b89c37/attachment-0001.html>
More information about the webkit-unassigned
mailing list