Title: [183273] trunk/Source/WebKit2
Revision
183273
Author
[email protected]
Date
2015-04-24 11:57:25 -0700 (Fri, 24 Apr 2015)

Log Message

CrashTracer: [USER] com.apple.WebKit.Networking at com.apple.WebKit: WebKit::NetworkResourceLoader::~NetworkResourceLoader + 14
https://bugs.webkit.org/show_bug.cgi?id=144147

Reviewed by Chris Dumez.

Storage::storeBodyAsBlob copies the std::function callback for handling mapped bodies in a thread.
This is thread safe only if the function copy is thread safe. It is currently not as we are capturing
RefPtr<NetworkResourceLoader> and NetworkResourceLoader doesn't use thread safe refcounting.

Fix by avoiding copying of the callback. Use same apporach for WriteOperation as we already use for
ReadOperation: count the active operations in progress and delete WriteOperation when everything is
finished. This way we don't need to copy the function out from WriteOperation.

* NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::ReadOperation::ReadOperation):
(WebKit::NetworkCache::Storage::WriteOperation::WriteOperation):

    Move definition here from the header.

(WebKit::NetworkCache::Storage::~Storage):
(WebKit::NetworkCache::Storage::storeBodyAsBlob):

    Increment the operation count when storing a blob, call finishWriteOperation when done.

(WebKit::NetworkCache::Storage::dispatchReadOperation):
(WebKit::NetworkCache::Storage::finishReadOperation):

    Count active operations instead of finished operations. This makes the code clearer.

(WebKit::NetworkCache::Storage::dispatchWriteOperation):
(WebKit::NetworkCache::Storage::finishWriteOperation):

    Mirror the way ReadOperations work.

* NetworkProcess/cache/NetworkCacheStorage.h:
(WebKit::NetworkCache::Storage::ReadOperation::ReadOperation): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (183272 => 183273)


--- trunk/Source/WebKit2/ChangeLog	2015-04-24 18:55:26 UTC (rev 183272)
+++ trunk/Source/WebKit2/ChangeLog	2015-04-24 18:57:25 UTC (rev 183273)
@@ -1,3 +1,42 @@
+2015-04-24  Antti Koivisto  <[email protected]>
+
+        CrashTracer: [USER] com.apple.WebKit.Networking at com.apple.WebKit: WebKit::NetworkResourceLoader::~NetworkResourceLoader + 14
+        https://bugs.webkit.org/show_bug.cgi?id=144147
+
+        Reviewed by Chris Dumez.
+
+        Storage::storeBodyAsBlob copies the std::function callback for handling mapped bodies in a thread.
+        This is thread safe only if the function copy is thread safe. It is currently not as we are capturing
+        RefPtr<NetworkResourceLoader> and NetworkResourceLoader doesn't use thread safe refcounting.
+
+        Fix by avoiding copying of the callback. Use same apporach for WriteOperation as we already use for
+        ReadOperation: count the active operations in progress and delete WriteOperation when everything is
+        finished. This way we don't need to copy the function out from WriteOperation.
+
+        * NetworkProcess/cache/NetworkCacheStorage.cpp:
+        (WebKit::NetworkCache::Storage::ReadOperation::ReadOperation):
+        (WebKit::NetworkCache::Storage::WriteOperation::WriteOperation):
+
+            Move definition here from the header.
+
+        (WebKit::NetworkCache::Storage::~Storage):
+        (WebKit::NetworkCache::Storage::storeBodyAsBlob):
+
+            Increment the operation count when storing a blob, call finishWriteOperation when done.
+
+        (WebKit::NetworkCache::Storage::dispatchReadOperation):
+        (WebKit::NetworkCache::Storage::finishReadOperation):
+
+            Count active operations instead of finished operations. This makes the code clearer.
+
+        (WebKit::NetworkCache::Storage::dispatchWriteOperation):
+        (WebKit::NetworkCache::Storage::finishWriteOperation):
+
+            Mirror the way ReadOperations work.
+
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+        (WebKit::NetworkCache::Storage::ReadOperation::ReadOperation): Deleted.
+
 2015-04-24  Timothy Hatcher  <[email protected]>
 
         REGRESSION: Web Inspector: Start Timeline Recording in Develop menu broken

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp (183272 => 183273)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp	2015-04-24 18:55:26 UTC (rev 183272)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp	2015-04-24 18:57:25 UTC (rev 183273)
@@ -49,6 +49,32 @@
 
 static double computeRecordWorth(FileTimes);
 
+struct Storage::ReadOperation {
+    ReadOperation(const Key& key, const RetrieveCompletionHandler& completionHandler)
+        : key(key)
+        , completionHandler(completionHandler)
+    { }
+
+    const Key key;
+    const RetrieveCompletionHandler completionHandler;
+    
+    std::unique_ptr<Record> resultRecord;
+    SHA1::Digest expectedBodyHash;
+    BlobStorage::Blob resultBodyBlob;
+    std::atomic<unsigned> activeCount { 0 };
+};
+
+struct Storage::WriteOperation {
+    WriteOperation(const Record& record, const MappedBodyHandler& mappedBodyHandler)
+        : record(record)
+        , mappedBodyHandler(mappedBodyHandler)
+    { }
+    
+    Record record;
+    MappedBodyHandler mappedBodyHandler;
+    std::atomic<unsigned> activeCount { 0 };
+};
+
 std::unique_ptr<Storage> Storage::open(const String& cachePath)
 {
     ASSERT(RunLoop::isMain());
@@ -87,6 +113,9 @@
     synchronize();
 }
 
+Storage::~Storage()
+{
+}
 
 String Storage::basePath() const
 {
@@ -351,25 +380,27 @@
     return Data(encoder.buffer(), encoder.bufferSize());
 }
 
-Optional<BlobStorage::Blob> Storage::storeBodyAsBlob(const Record& record, const MappedBodyHandler& mappedBodyHandler)
+Optional<BlobStorage::Blob> Storage::storeBodyAsBlob(WriteOperation& writeOperation)
 {
-    auto bodyPath = bodyPathForKey(record.key);
+    auto bodyPath = bodyPathForKey(writeOperation.record.key);
 
     // Store the body.
-    auto blob = m_blobStorage.add(bodyPath, record.body);
+    auto blob = m_blobStorage.add(bodyPath, writeOperation.record.body);
     if (blob.data.isNull())
         return { };
 
-    auto hash = record.key.hash();
-    RunLoop::main().dispatch([this, blob, hash, mappedBodyHandler] {
+    ++writeOperation.activeCount;
+
+    RunLoop::main().dispatch([this, blob, &writeOperation] {
         if (m_bodyFilter)
-            m_bodyFilter->add(hash);
+            m_bodyFilter->add(writeOperation.record.key.hash());
         if (m_synchronizationInProgress)
-            m_bodyFilterHashesAddedDuringSynchronization.append(hash);
+            m_bodyFilterHashesAddedDuringSynchronization.append(writeOperation.record.key.hash());
 
-        if (mappedBodyHandler)
-            mappedBodyHandler(blob.data);
+        if (writeOperation.mappedBodyHandler)
+            writeOperation.mappedBodyHandler(blob.data);
 
+        finishWriteOperation(writeOperation);
     });
     return blob;
 }
@@ -424,6 +455,12 @@
 
     auto recordPath = recordPathForKey(readOperation.key);
 
+    ++readOperation.activeCount;
+
+    bool shouldGetBodyBlob = !m_bodyFilter || m_bodyFilter->mayContain(readOperation.key.hash());
+    if (shouldGetBodyBlob)
+        ++readOperation.activeCount;
+
     RefPtr<IOChannel> channel = IOChannel::open(recordPath, IOChannel::Type::Read);
     channel->read(0, std::numeric_limits<size_t>::max(), &ioQueue(), [this, &readOperation](const Data& fileData, int error) {
         if (!error)
@@ -431,11 +468,8 @@
         finishReadOperation(readOperation);
     });
 
-    bool shouldGetBodyBlob = !m_bodyFilter || m_bodyFilter->mayContain(readOperation.key.hash());
-    if (!shouldGetBodyBlob) {
-        finishReadOperation(readOperation);
+    if (!shouldGetBodyBlob)
         return;
-    }
 
     // Read the body blob in parallel with the record read.
     ioQueue().dispatch([this, &readOperation] {
@@ -447,9 +481,9 @@
 
 void Storage::finishReadOperation(ReadOperation& readOperation)
 {
+    ASSERT(readOperation.activeCount);
     // Record and body blob reads must finish.
-    bool isComplete = ++readOperation.finishedCount == 2;
-    if (!isComplete)
+    if (--readOperation.activeCount)
         return;
 
     RunLoop::main().dispatch([this, &readOperation] {
@@ -534,7 +568,7 @@
     return bodyData.size() > maximumInlineBodySize;
 }
 
-void Storage::dispatchWriteOperation(const WriteOperation& writeOperation)
+void Storage::dispatchWriteOperation(WriteOperation& writeOperation)
 {
     ASSERT(RunLoop::isMain());
     ASSERT(m_activeWriteOperations.contains(&writeOperation));
@@ -548,8 +582,10 @@
 
         WebCore::makeAllDirectories(partitionPath);
 
+        ++writeOperation.activeCount;
+
         bool shouldStoreAsBlob = shouldStoreBodyAsBlob(writeOperation.record.body);
-        auto bodyBlob = shouldStoreAsBlob ? storeBodyAsBlob(writeOperation.record, writeOperation.mappedBodyHandler) : Nullopt;
+        auto bodyBlob = shouldStoreAsBlob ? storeBodyAsBlob(writeOperation) : Nullopt;
 
         auto recordData = encodeRecord(writeOperation.record, bodyBlob);
 
@@ -565,9 +601,15 @@
     });
 }
 
-void Storage::finishWriteOperation(const WriteOperation& writeOperation)
+void Storage::finishWriteOperation(WriteOperation& writeOperation)
 {
+    ASSERT(RunLoop::isMain());
+    ASSERT(writeOperation.activeCount);
     ASSERT(m_activeWriteOperations.contains(&writeOperation));
+
+    if (--writeOperation.activeCount)
+        return;
+
     m_activeWriteOperations.remove(&writeOperation);
     dispatchPendingWriteOperations();
 

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (183272 => 183273)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-04-24 18:55:26 UTC (rev 183272)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h	2015-04-24 18:57:25 UTC (rev 183273)
@@ -87,6 +87,8 @@
     String versionPath() const;
     String recordsPath() const;
 
+    ~Storage();
+
 private:
     Storage(const String& directoryPath);
 
@@ -99,33 +101,17 @@
     void shrinkIfNeeded();
     void shrink();
 
-    struct ReadOperation {
-        ReadOperation(const Key& key, const RetrieveCompletionHandler& completionHandler)
-            : key(key)
-            , completionHandler(completionHandler)
-        { }
-
-        const Key key;
-        const RetrieveCompletionHandler completionHandler;
-        
-        std::unique_ptr<Record> resultRecord;
-        SHA1::Digest expectedBodyHash;
-        BlobStorage::Blob resultBodyBlob;
-        std::atomic<unsigned> finishedCount { 0 };
-    };
+    struct ReadOperation;
     void dispatchReadOperation(ReadOperation&);
     void dispatchPendingReadOperations();
     void finishReadOperation(ReadOperation&);
 
-    struct WriteOperation {
-        Record record;
-        MappedBodyHandler mappedBodyHandler;
-    };
-    void dispatchWriteOperation(const WriteOperation&);
+    struct WriteOperation;
+    void dispatchWriteOperation(WriteOperation&);
     void dispatchPendingWriteOperations();
-    void finishWriteOperation(const WriteOperation&);
+    void finishWriteOperation(WriteOperation&);
 
-    Optional<BlobStorage::Blob> storeBodyAsBlob(const Record&, const MappedBodyHandler&);
+    Optional<BlobStorage::Blob> storeBodyAsBlob(WriteOperation&);
     Data encodeRecord(const Record&, Optional<BlobStorage::Blob>);
     void readRecord(ReadOperation&, const Data&);
 
@@ -160,8 +146,8 @@
     Deque<std::unique_ptr<ReadOperation>> m_pendingReadOperationsByPriority[maximumRetrievePriority + 1];
     HashSet<std::unique_ptr<ReadOperation>> m_activeReadOperations;
 
-    Deque<std::unique_ptr<const WriteOperation>> m_pendingWriteOperations;
-    HashSet<std::unique_ptr<const WriteOperation>> m_activeWriteOperations;
+    Deque<std::unique_ptr<WriteOperation>> m_pendingWriteOperations;
+    HashSet<std::unique_ptr<WriteOperation>> m_activeWriteOperations;
 
     Ref<WorkQueue> m_ioQueue;
     Ref<WorkQueue> m_backgroundIOQueue;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to