Bug 86911

Summary: IndexedDB: "ASSERTION FAILED: !m_requestFinished" hit in IDBRequest::dispatchEvent
Product: WebKit Reporter: Joshua Bell <jsbell>
Component: WebCore Misc.Assignee: Joshua Bell <jsbell>
Status: RESOLVED FIXED    
Severity: Normal CC: alecflett, dgrogan, tony, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 90412    
Bug Blocks:    
Attachments:
Description Flags
Repro case
none
Real repro case
none
Patch
none
Patch none

Description Joshua Bell 2012-05-18 15:41:34 PDT
Created attachment 142799 [details]
Repro case

Seen in DumpRenderTree with attached LayoutTest (which could be dropped into storage/indexeddb for dependencies):

crash log for DumpRenderTree (pid 8867):
STDERR: ASSERTION FAILED: !m_requestFinished
STDERR: ../../third_party/WebKit/Source/WebCore/Modules/indexeddb/IDBRequest.cpp(342) : virtual bool WebCore::IDBRequest::dispatchEvent(WTF::PassRefPtr<WebCore::Event>)

What's probably happening is the transaction is completing, and IDBTransaction::onComplete() calls IDBTransaction::closeOpenCursors() calls IDBCursor::close() calls IDBRequest::finishCursor() which sets m_cursorFinished, which allows m_requestFinished to be set. This may be happening too early.
Comment 1 Joshua Bell 2012-05-18 15:47:24 PDT
Created attachment 142804 [details]
Real repro case
Comment 2 Joshua Bell 2012-05-18 15:48:16 PDT
Comment on attachment 142799 [details]
Repro case

Whoops. First repro had been reduced too far and I was testing the wrong file. Look at the second one that has noSuchFunction
Comment 3 Joshua Bell 2012-05-21 11:42:16 PDT
(In reply to comment #2)
> (From update of attachment 142799 [details])
> Whoops. First repro had been reduced too far and I was testing the wrong file. Look at the second one that has noSuchFunction

... and I admit I now have no idea what's going on. Changing the ordering of lines in the minimal repro - e.g. when the non-existent handler is assigned - makes the issue go away, which means my previous theory is incorrect.
Comment 4 Joshua Bell 2012-06-14 16:22:45 PDT
Ah, here's the key bit:

    request = store.openCursor();
    request.onsuccess = function () {
        event.target.result.continue();
        throw "foo";
    };

If an exception is thrown in the event handler after the continue() is called the ASSERT is hit.
Comment 5 Joshua Bell 2012-06-14 16:43:57 PDT
The uncaught exception is causing the transaction to be aborted, which closes the cursor which sets m_requestFinished on the IDBRequest between an event being enqueued and it being dispatched.
Comment 6 Joshua Bell 2012-06-14 17:08:31 PDT
(In reply to comment #5)
> The uncaught exception is causing the transaction to be aborted, which closes the cursor which sets m_requestFinished on the IDBRequest between an event being enqueued and it being dispatched.

Scratch that, not quite correct. Here's what's going on:

* success event fired at the cursor request
* success event dispatched by the cursor request
* script calls continue(), which queues an task in the transaction
* script raises an exception, which aborts the transaction
* transaction aborting closes the cursor
* transaction aborting aborts the queued task, which fires an error event at the cursor request
* cursor request attempt to dispatch the error event, and ASSERTs
Comment 7 Joshua Bell 2012-06-14 17:18:34 PDT
Seems like we need to untangle things slightly - either the cursor shouldn't "finish" the request while there are outstanding events, or we should allow the error event to be dispatched even if the cursor is closed. Given that dispatch can be arbitrarily delayed, it seems like the latter is more tractable.

(The timing difference between event queuing and dispatching is tricksy.)
Comment 8 Joshua Bell 2012-07-09 13:40:05 PDT
Note that this still repros after the untangling in 90412 (which makes sense because that patch should only impact multiprocess ports, whereas this repros DRT), but any fix here should wait until that lands since it touches related code.
Comment 9 Joshua Bell 2012-07-19 15:21:09 PDT
Created attachment 153361 [details]
Patch
Comment 10 Joshua Bell 2012-07-19 15:24:25 PDT
Counting only "interesting" LOC, IDBRequest.cpp is now 20% ASSERTs!

dgrogan@, alecflett@ - please take a look.
Comment 11 David Grogan 2012-07-20 14:20:24 PDT
Comment on attachment 153361 [details]
Patch

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

LGTM

> Source/WebCore/Modules/indexeddb/IDBRequest.h:76
>      bool resetReadyState(IDBTransaction*);

Can this line be deleted?
Comment 12 Joshua Bell 2012-07-20 14:44:43 PDT
Created attachment 153605 [details]
Patch
Comment 13 Joshua Bell 2012-07-20 14:45:36 PDT
(In reply to comment #11)
> > Source/WebCore/Modules/indexeddb/IDBRequest.h:76
> >      bool resetReadyState(IDBTransaction*);
> 
> Can this line be deleted?

Good catch - deleted!

tony@ - r?
Comment 14 WebKit Review Bot 2012-07-20 16:51:41 PDT
Comment on attachment 153605 [details]
Patch

Clearing flags on attachment: 153605

Committed r123275: <http://trac.webkit.org/changeset/123275>
Comment 15 WebKit Review Bot 2012-07-20 16:51:45 PDT
All reviewed patches have been landed.  Closing bug.