Bug 144661 - [iOS] Close all open databases in expiration handler of process assertion
Summary: [iOS] Close all open databases in expiration handler of process assertion
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: 528+ (Nightly build)
Hardware: iPhone / iPad iOS 8.2
: P2 Normal
Assignee: Daniel Bates
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-05-05 20:37 PDT by Daniel Bates
Modified: 2015-05-11 15:58 PDT (History)
4 users (show)

See Also:


Attachments
Part 1: Add infrastructure to interrupt all databases (6.51 KB, patch)
2015-05-05 20:40 PDT, Daniel Bates
no flags Details | Formatted Diff | Diff
Patch (37.40 KB, patch)
2015-05-07 21:29 PDT, Daniel Bates
no flags Details | Formatted Diff | Diff
Patch (37.04 KB, patch)
2015-05-07 21:36 PDT, Daniel Bates
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Bates 2015-05-05 20:37:30 PDT
We should interrupt all in-progress database transactions on expiration of a UIProcess process assertion so that the WebProcess is not terminated on suspension because it is holding a lock on a database file (since it is performing a database transaction).
Comment 1 Daniel Bates 2015-05-05 20:40:48 PDT
Created attachment 252444 [details]
Part 1: Add infrastructure to interrupt all databases
Comment 2 Radar WebKit Bug Importer 2015-05-06 15:13:23 PDT
<rdar://problem/20845052>
Comment 3 Daniel Bates 2015-05-07 21:29:28 PDT
Created attachment 252681 [details]
Patch
Comment 4 Daniel Bates 2015-05-07 21:36:21 PDT
Created attachment 252682 [details]
Patch

Remove whitespace inadvertently added to -[WebDatabaseManager endBackgroundTask].
Comment 5 Darin Adler 2015-05-10 15:11:18 PDT
Comment on attachment 252682 [details]
Patch

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

> Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp:311
> +    Vector<RefPtr<Database>> openDatabases;

Might be able to use Vector<Ref<Database>> here instead.

> Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp:321
> +        for (auto& databaseOrigin : *m_openDatabaseMap) {
> +            for (auto& databaseName : *databaseOrigin.value) {
> +                for (auto& database : *databaseName.value)
> +                    openDatabases.append(database);
> +            }
> +        }

This should be written using values():

    for (auto& nameMap : m_openDatabaseMap->values()) {
        for (auto& set : nameMap->values()) {
            for (auto& database : *set)
                openDatabases.append(database);
        }
    }

> Source/WebKit2/UIProcess/ProcessThrottler.h:44
> +class ProcessThrottler : public ProcessAssertionClient {

Please make this private inheritance instead.

> Source/WebKit2/UIProcess/ProcessThrottler.h:61
> +    // ProcessAssertionClient
> +    void assertionWillExpireImminently() override;

Please make this private.

> Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:47
> +- (void)addClient:(ProcessAssertionClient *)client;
> +- (void)removeClient:(ProcessAssertionClient *)client;

Wrong formatting. ProcessAssertionClient isn’t an Objective-C class. Also, these arguments should be references, not pointers.

> Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:56
> +    HashSet<ProcessAssertionClient *> _clients;

Wrong formatting. ProcessAssertionClient isn’t an Objective-C class.

> Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:111
> +            for (auto* client : _clients)
> +                client->assertionWillExpireImminently();

What guarantees the body of assertionWillExpireImminently won’t call something that could reenter and call addClient: or removeClient: while iterating _clients?
Comment 6 Daniel Bates 2015-05-11 09:58:30 PDT
(In reply to comment #5)
> > Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp:311
> > +    Vector<RefPtr<Database>> openDatabases;
> 
> Might be able to use Vector<Ref<Database>> here instead.
> 

Will use Vector<Ref<Database>>.

> > Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp:321
> > +        for (auto& databaseOrigin : *m_openDatabaseMap) {
> > +            for (auto& databaseName : *databaseOrigin.value) {
> > +                for (auto& database : *databaseName.value)
> > +                    openDatabases.append(database);
> > +            }
> > +        }
> 
> This should be written using values():
> 
>     for (auto& nameMap : m_openDatabaseMap->values()) {
>         for (auto& set : nameMap->values()) {
>             for (auto& database : *set)
>                 openDatabases.append(database);
>         }
>     }
> 

Will fix.

> > Source/WebKit2/UIProcess/ProcessThrottler.h:44
> > +class ProcessThrottler : public ProcessAssertionClient {
> 
> Please make this private inheritance instead.
> 

Will use private inheritance.

> > Source/WebKit2/UIProcess/ProcessThrottler.h:61
> > +    // ProcessAssertionClient
> > +    void assertionWillExpireImminently() override;
> 
> Please make this private.
> 

Will make this private.

> > Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:47
> > +- (void)addClient:(ProcessAssertionClient *)client;
> > +- (void)removeClient:(ProcessAssertionClient *)client;
> 
> Wrong formatting. ProcessAssertionClient isn’t an Objective-C class. Also,
> these arguments should be references, not pointers.
> 

Will use references instead of pointers and fix formatting.

> > Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:56
> > +    HashSet<ProcessAssertionClient *> _clients;
> 
> Wrong formatting. ProcessAssertionClient isn’t an Objective-C class.
> 

Will fix formatting.

> > Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:111
> > +            for (auto* client : _clients)
> > +                client->assertionWillExpireImminently();
> 
> What guarantees the body of assertionWillExpireImminently won’t call
> something that could reenter and call addClient: or removeClient: while
> iterating _clients?

Will copy HashSet<ProcessAssertionClient*> to a vector and iterate over the vector to prevent issues with such reentrancy.
Comment 7 Daniel Bates 2015-05-11 10:28:40 PDT
Committed r184105: <http://trac.webkit.org/changeset/184105>
Comment 8 Daniel Bates 2015-05-11 12:02:39 PDT
(In reply to comment #6)
> > > Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm:111
> > > +            for (auto* client : _clients)
> > > +                client->assertionWillExpireImminently();
> > 
> > What guarantees the body of assertionWillExpireImminently won’t call
> > something that could reenter and call addClient: or removeClient: while
> > iterating _clients?
> 
> Will copy HashSet<ProcessAssertionClient*> to a vector and iterate over the
> vector to prevent issues with such reentrancy.

We should also ensure that client is still in the list of clients managed by WKProcessAssertionBackgroundTaskManager. Filed bug #144880 to address this.