Title: [247975] branches/safari-608-branch/Source/WebKit
Revision
247975
Author
alanc...@apple.com
Date
2019-07-29 20:55:24 -0700 (Mon, 29 Jul 2019)

Log Message

Cherry-pick r247784. rdar://problem/53647468

    Crash under WebKit:WTF::Detail::CallableWrapper<WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking(WTF::CompletionHandler<void ()>&&)::$_32::operator()()::'lambda'(), void>::call
    https://bugs.webkit.org/show_bug.cgi?id=200071
    <rdar://problem/53335583>

    Reviewed by Brent Fulgham and Youenn Fablet.

    The WebResourceLoadStatisticsStore is a main thread object. In its destructor, it was dispatching
    to the background queue to destroy the m_statisticsStore / m_persistentStorage data members, which
    live on the background queue. It would then synchronously wait for the background queue to finish
    destroying them. The idea was to guarantee that the ResourceLoadStatisticsMemoryStore and the
    ResourceLoadStatisticsPersistentStorage would never outlive the WebResourceLoadStatisticsStore,
    given that they keep a raw pointer back to the WebResourceLoadStatisticsStore (via m_store data
    member).

    The issue is that *while* the WebResourceLoadStatisticsStore destructor is running on the main
    thread, the background queue may be running code in ResourceLoadStatisticsMemoryStore or
    ResourceLoadStatisticsPersistentStorage which refs the WebResourceLoadStatisticsStore, even
    though its ref count has already reached 0. It is actually a common pattern in
    ResourceLoadStatisticsMemoryStore to call RunLoop::main().dispatch() and ref their m_store in
    the lambda, so that they can interact with the WebResourceLoadStatisticsStore.

    To address the issue, we now destroy m_statisticsStore / m_persistentStorage *before* the
    WebResourceLoadStatisticsStore destructor runs. The NetworkSession destructor now calls
    WebResourceLoadStatisticsStore::didDestroyNetworkSession() which takes care of destroying
    m_statisticsStore / m_persistentStorage on the background queue, synchronously. The
    WebResourceLoadStatisticsStore destructor will only run later, once all remaining references
    to it are gone.

    * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
    (WebKit::WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore):
    (WebKit::WebResourceLoadStatisticsStore::didDestroyNetworkSession):
    * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
    * NetworkProcess/NetworkSession.cpp:
    (WebKit::NetworkSession::~NetworkSession):

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247784 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Diff

Modified: branches/safari-608-branch/Source/WebKit/ChangeLog (247974 => 247975)


--- branches/safari-608-branch/Source/WebKit/ChangeLog	2019-07-30 03:55:21 UTC (rev 247974)
+++ branches/safari-608-branch/Source/WebKit/ChangeLog	2019-07-30 03:55:24 UTC (rev 247975)
@@ -1,5 +1,84 @@
 2019-07-29  Alan Coon  <alanc...@apple.com>
 
+        Cherry-pick r247784. rdar://problem/53647468
+
+    Crash under WebKit:WTF::Detail::CallableWrapper<WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking(WTF::CompletionHandler<void ()>&&)::$_32::operator()()::'lambda'(), void>::call
+    https://bugs.webkit.org/show_bug.cgi?id=200071
+    <rdar://problem/53335583>
+    
+    Reviewed by Brent Fulgham and Youenn Fablet.
+    
+    The WebResourceLoadStatisticsStore is a main thread object. In its destructor, it was dispatching
+    to the background queue to destroy the m_statisticsStore / m_persistentStorage data members, which
+    live on the background queue. It would then synchronously wait for the background queue to finish
+    destroying them. The idea was to guarantee that the ResourceLoadStatisticsMemoryStore and the
+    ResourceLoadStatisticsPersistentStorage would never outlive the WebResourceLoadStatisticsStore,
+    given that they keep a raw pointer back to the WebResourceLoadStatisticsStore (via m_store data
+    member).
+    
+    The issue is that *while* the WebResourceLoadStatisticsStore destructor is running on the main
+    thread, the background queue may be running code in ResourceLoadStatisticsMemoryStore or
+    ResourceLoadStatisticsPersistentStorage which refs the WebResourceLoadStatisticsStore, even
+    though its ref count has already reached 0. It is actually a common pattern in
+    ResourceLoadStatisticsMemoryStore to call RunLoop::main().dispatch() and ref their m_store in
+    the lambda, so that they can interact with the WebResourceLoadStatisticsStore.
+    
+    To address the issue, we now destroy m_statisticsStore / m_persistentStorage *before* the
+    WebResourceLoadStatisticsStore destructor runs. The NetworkSession destructor now calls
+    WebResourceLoadStatisticsStore::didDestroyNetworkSession() which takes care of destroying
+    m_statisticsStore / m_persistentStorage on the background queue, synchronously. The
+    WebResourceLoadStatisticsStore destructor will only run later, once all remaining references
+    to it are gone.
+    
+    * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+    (WebKit::WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore):
+    (WebKit::WebResourceLoadStatisticsStore::didDestroyNetworkSession):
+    * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+    * NetworkProcess/NetworkSession.cpp:
+    (WebKit::NetworkSession::~NetworkSession):
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247784 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-07-24  Chris Dumez  <cdu...@apple.com>
+
+            Crash under WebKit:WTF::Detail::CallableWrapper<WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking(WTF::CompletionHandler<void ()>&&)::$_32::operator()()::'lambda'(), void>::call
+            https://bugs.webkit.org/show_bug.cgi?id=200071
+            <rdar://problem/53335583>
+
+            Reviewed by Brent Fulgham and Youenn Fablet.
+
+            The WebResourceLoadStatisticsStore is a main thread object. In its destructor, it was dispatching
+            to the background queue to destroy the m_statisticsStore / m_persistentStorage data members, which
+            live on the background queue. It would then synchronously wait for the background queue to finish
+            destroying them. The idea was to guarantee that the ResourceLoadStatisticsMemoryStore and the
+            ResourceLoadStatisticsPersistentStorage would never outlive the WebResourceLoadStatisticsStore,
+            given that they keep a raw pointer back to the WebResourceLoadStatisticsStore (via m_store data
+            member).
+
+            The issue is that *while* the WebResourceLoadStatisticsStore destructor is running on the main
+            thread, the background queue may be running code in ResourceLoadStatisticsMemoryStore or
+            ResourceLoadStatisticsPersistentStorage which refs the WebResourceLoadStatisticsStore, even
+            though its ref count has already reached 0. It is actually a common pattern in
+            ResourceLoadStatisticsMemoryStore to call RunLoop::main().dispatch() and ref their m_store in
+            the lambda, so that they can interact with the WebResourceLoadStatisticsStore.
+
+            To address the issue, we now destroy m_statisticsStore / m_persistentStorage *before* the
+            WebResourceLoadStatisticsStore destructor runs. The NetworkSession destructor now calls
+            WebResourceLoadStatisticsStore::didDestroyNetworkSession() which takes care of destroying
+            m_statisticsStore / m_persistentStorage on the background queue, synchronously. The
+            WebResourceLoadStatisticsStore destructor will only run later, once all remaining references
+            to it are gone.
+
+            * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+            (WebKit::WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore):
+            (WebKit::WebResourceLoadStatisticsStore::didDestroyNetworkSession):
+            * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+            * NetworkProcess/NetworkSession.cpp:
+            (WebKit::NetworkSession::~NetworkSession):
+
+2019-07-29  Alan Coon  <alanc...@apple.com>
+
         Cherry-pick r247782. rdar://problem/53647473
 
     SYS___pthread_markcancel is sometimes used by libwebrtc

Modified: branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (247974 => 247975)


--- branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-07-30 03:55:21 UTC (rev 247974)
+++ branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-07-30 03:55:24 UTC (rev 247975)
@@ -180,7 +180,15 @@
 WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore()
 {
     ASSERT(RunLoop::isMain());
+    ASSERT(!m_statisticsStore);
+    ASSERT(!m_persistentStorage);
+}
 
+void WebResourceLoadStatisticsStore::didDestroyNetworkSession()
+{
+    ASSERT(RunLoop::isMain());
+
+    m_networkSession = nullptr;
     flushAndDestroyPersistentStore();
 }
 
@@ -335,6 +343,9 @@
             return;
         case StorageAccessStatus::RequiresUserPrompt:
             {
+            if (!m_networkSession)
+                return completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::No);
+
             CompletionHandler<void(bool)> requestConfirmationCompletionHandler = [this, protectedThis = protectedThis.copyRef(), subFrameDomain, topFrameDomain, frameID, pageID, completionHandler = WTFMove(completionHandler)] (bool userDidGrantAccess) mutable {
                 if (userDidGrantAccess)
                     grantStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID, StorageAccessPromptWasShown::Yes, WTFMove(completionHandler));
@@ -358,13 +369,11 @@
             return;
         }
 
-        if (m_statisticsStore) {
-            m_statisticsStore->requestStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, [statusHandler = WTFMove(statusHandler)](StorageAccessStatus status) mutable {
-                postTaskReply([statusHandler = WTFMove(statusHandler), status]() mutable {
-                    statusHandler(status);
-                });
+        m_statisticsStore->requestStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, [statusHandler = WTFMove(statusHandler)](StorageAccessStatus status) mutable {
+            postTaskReply([statusHandler = WTFMove(statusHandler), status]() mutable {
+                statusHandler(status);
             });
-        }
+        });
     });
 }
 

Modified: branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (247974 => 247975)


--- branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-07-30 03:55:21 UTC (rev 247974)
+++ branches/safari-608-branch/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-07-30 03:55:24 UTC (rev 247975)
@@ -94,6 +94,8 @@
 
     ~WebResourceLoadStatisticsStore();
 
+    void didDestroyNetworkSession();
+
     static const OptionSet<WebsiteDataType>& monitoredDataTypes();
 
     WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }

Modified: branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp (247974 => 247975)


--- branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-07-30 03:55:21 UTC (rev 247974)
+++ branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-07-30 03:55:24 UTC (rev 247975)
@@ -94,10 +94,25 @@
 
 NetworkSession::~NetworkSession()
 {
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    destroyResourceLoadStatistics();
+#endif
+
     m_storageManager->resume();
     m_storageManager->waitUntilTasksFinished();
 }
 
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+void NetworkSession::destroyResourceLoadStatistics()
+{
+    if (!m_resourceLoadStatistics)
+        return;
+
+    m_resourceLoadStatistics->didDestroyNetworkSession();
+    m_resourceLoadStatistics = nullptr;
+}
+#endif
+
 void NetworkSession::invalidateAndCancel()
 {
     for (auto* task : m_dataTaskSet)
@@ -116,7 +131,7 @@
 {
     ASSERT(!m_isInvalidated);
     if (!enable) {
-        m_resourceLoadStatistics = nullptr;
+        destroyResourceLoadStatistics();
         return;
     }
 

Modified: branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.h (247974 => 247975)


--- branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.h	2019-07-30 03:55:21 UTC (rev 247974)
+++ branches/safari-608-branch/Source/WebKit/NetworkProcess/NetworkSession.h	2019-07-30 03:55:24 UTC (rev 247975)
@@ -110,6 +110,10 @@
 protected:
     NetworkSession(NetworkProcess&, PAL::SessionID, String&& localStorageDirectory, SandboxExtension::Handle&);
 
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    void destroyResourceLoadStatistics();
+#endif
+
     PAL::SessionID m_sessionID;
     Ref<NetworkProcess> m_networkProcess;
     HashSet<NetworkDataTask*> m_dataTaskSet;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to