Bug 180518

Summary: Crash in WebCore::SQLiteStatement::prepare() from ServiceWorker I/O Thread
Product: WebKit Reporter: Daniel Bates <dbates>
Component: Service WorkersAssignee: Brady Eidson <beidson>
Status: NEW ---    
Severity: Normal CC: beidson, cdumez, youennf
Priority: P2    
Version: WebKit Local Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=118563
https://bugs.webkit.org/show_bug.cgi?id=180589
Attachments:
Description Flags
Patch cdumez: review+

Description Daniel Bates 2017-12-06 19:43:46 PST
In the EWS results (attachment #328671 [details]) after processing the patch on bug #180512, I noticed that the following tests are crashing in the ServiceWorker I/O Thread inside WebCore::SQLiteStatement::prepare():

http/tests/inspector/network/resource-response-service-worker.html
imported/w3c/web-platform-tests/streams/readable-byte-streams/brand-checks.serviceworker.https.html	

Paraphrasing the crash log for http/tests/inspector/network/resource-response-service-worker.html (both crashes have the same backtrace and exception code):

[[
Process:               com.apple.WebKit.Storage.Development [77629]
Path:                  /Volumes/VOLUME/*/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.Storage.xpc/Contents/MacOS/com.apple.WebKit.Storage.Development
Identifier:            com.apple.WebKit.Storage.Development
Version:               605+ (605.1.16+)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
User ID:               501

Date/Time:             2017-12-06 18:18:26.347 -0800
OS Version:            Mac OS X 10.11.6 (15G17023)
Report Version:        11
Anonymous UUID:        18EE2525-DEB2-9EB7-627F-5FA60686285B

Time Awake Since Boot: 8200 seconds

System Integrity Protection: disabled

Crashed Thread:        3  ServiceWorker I/O Thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000018
Exception Note:        EXC_CORPSE_NOTIFY

Thread 3 Crashed:: ServiceWorker I/O Thread
0   com.apple.WebCore             	0x0000000105c17ec7 WebCore::SQLiteStatement::prepare() + 23 (atomic:879)
1   com.apple.WebCore             	0x0000000105c1794f WebCore::SQLiteDatabase::executeCommand(WTF::String const&) + 47 (SQLiteStatement.cpp:133)
2   com.apple.WebCore             	0x0000000105c1b061 WebCore::SQLiteTransaction::begin() + 129 (SQLiteTransaction.cpp:67)
3   com.apple.WebCore             	0x0000000105f86277 WebCore::RegistrationDatabase::doPushChanges(WTF::Vector<WebCore::ServiceWorkerContextData, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&) + 55 (memory:2635)
4   com.apple.JavaScriptCore      	0x0000000109230f5f WTF::CrossThreadTaskHandler::taskRunLoop() + 127 (memory:2656)
5   com.apple.JavaScriptCore      	0x00000001092692a4 WTF::Thread::entryPoint(WTF::Thread::NewThreadContext*) + 228 (memory:2657)
6   com.apple.JavaScriptCore      	0x000000010926a899 WTF::wtfThreadEntryPoint(void*) + 9 (ThreadingPthreads.cpp:223)
7   libsystem_pthread.dylib       	0x00007fff951ed99d _pthread_body + 131
8   libsystem_pthread.dylib       	0x00007fff951ed91a _pthread_start + 168
9   libsystem_pthread.dylib       	0x00007fff951eb351 thread_start + 13
]]
Comment 1 youenn fablet 2017-12-08 09:09:14 PST
I also got the same crash in EWS bot in processing results of https://bugs.webkit.org/show_bug.cgi?id=179641
Comment 2 Chris Dumez 2017-12-08 09:28:59 PST
What makes sure m_database is destroyed on the background thread? I see this assertion  ASSERT(!m_database); in the ~RegistrationDatabase() destructor (which gets called on the main thread) but I do not see the code that takes care of clearing m_database on the BG thread.
Comment 3 Brady Eidson 2017-12-08 10:10:14 PST
(In reply to Chris Dumez from comment #2)
> What makes sure m_database is destroyed on the background thread? I see this
> assertion  ASSERT(!m_database); in the ~RegistrationDatabase() destructor
> (which gets called on the main thread) but I do not see the code that takes
> care of clearing m_database on the BG thread.

The RegistrationDatabase is never destroyed.
Comment 4 Brady Eidson 2017-12-08 10:11:41 PST
(In reply to Brady Eidson from comment #3)
> (In reply to Chris Dumez from comment #2)
> > What makes sure m_database is destroyed on the background thread? I see this
> > assertion  ASSERT(!m_database); in the ~RegistrationDatabase() destructor
> > (which gets called on the main thread) but I do not see the code that takes
> > care of clearing m_database on the BG thread.
> 
> The RegistrationDatabase is never destroyed.

Elaborating: Are SWServers ever destroyed?
If not, then RegistrationStores aren't, and RegistrationDatabases aren't.
Comment 5 Brady Eidson 2017-12-08 10:15:40 PST
I actually think what's happening is a pushChanges() is happening without an m_database
Comment 6 Brady Eidson 2017-12-08 10:16:16 PST
Indeed, there's no protection against database operations happening without a valid database. Adding that soon.
Comment 7 Brady Eidson 2017-12-08 10:16:39 PST
(Would be great to know why the DB isn't being created)
Comment 8 Brady Eidson 2017-12-08 10:49:52 PST
Created attachment 328833 [details]
Patch
Comment 9 Chris Dumez 2017-12-08 10:52:27 PST
Comment on attachment 328833 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=328833&action=review

> Source/WebCore/workers/service/server/RegistrationDatabase.cpp:204
> +    if (!m_successfullyOpened) {

If you call pushChanges() right away after constructing the RegistrationDatabase, m_successfullyOpened may not have been set to true yet :/
Comment 10 Brady Eidson 2017-12-08 10:54:19 PST
(In reply to Chris Dumez from comment #9)
> Comment on attachment 328833 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=328833&action=review
> 
> > Source/WebCore/workers/service/server/RegistrationDatabase.cpp:204
> > +    if (!m_successfullyOpened) {
> 
> If you call pushChanges() right away after constructing the
> RegistrationDatabase, m_successfullyOpened may not have been set to true yet
> :/

Such a thing does not happen, though.
Comment 11 Brady Eidson 2017-12-08 10:54:45 PST
(In reply to Brady Eidson from comment #10)
> (In reply to Chris Dumez from comment #9)
> > Comment on attachment 328833 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=328833&action=review
> > 
> > > Source/WebCore/workers/service/server/RegistrationDatabase.cpp:204
> > > +    if (!m_successfullyOpened) {
> > 
> > If you call pushChanges() right away after constructing the
> > RegistrationDatabase, m_successfullyOpened may not have been set to true yet
> > :/
> 
> Such a thing does not happen, though.

Correction: *should* not happen
Comment 12 Chris Dumez 2017-12-08 10:58:30 PST
Comment on attachment 328833 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=328833&action=review

> Source/WebCore/workers/service/server/RegistrationDatabase.cpp:205
> +        LOG_ERROR("Attempt to push changes to SW registration database that is not open");

Should be RELEASE_LOG_ERROR.
Comment 13 Brady Eidson 2017-12-08 10:59:52 PST
Going with the one in 180587 for now, will revisit later. (I really need to get 180573 resolved)
Comment 14 Chris Dumez 2017-12-08 11:20:43 PST
Brady and I think the real underlying issue is https://bugs.webkit.org/show_bug.cgi?id=180589.