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;