Network Cache: Crash in WebCore::CachedResource::tryReplaceEncodedData
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cache / NetworkCacheIOChannelCocoa.mm
index 456119400cf1ecdc208611c10824a6e2254635cf..b1629403334c67bf97c94c7fe763cf01e401c738 100644 (file)
 namespace WebKit {
 namespace NetworkCache {
 
-IOChannel::IOChannel(int fd)
-    : m_fileDescriptor(fd)
-{
-    m_dispatchIO = adoptDispatch(dispatch_io_create(DISPATCH_IO_RANDOM, fd, dispatch_get_main_queue(), [fd](int) {
-        close(fd);
-    }));
-    ASSERT(m_dispatchIO.get());
-    // This makes the channel read/write all data before invoking the handlers.
-    dispatch_io_set_low_water(m_dispatchIO.get(), std::numeric_limits<size_t>::max());
-}
-
-Ref<IOChannel> IOChannel::open(const String& filePath, IOChannel::Type type)
+IOChannel::IOChannel(const String& filePath, Type type)
+    : m_path(filePath)
+    , m_type(type)
 {
+    auto path = WebCore::fileSystemRepresentation(filePath);
     int oflag;
     mode_t mode;
 
-    switch (type) {
+    switch (m_type) {
     case Type::Create:
-        oflag = O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK;
+        // We don't want to truncate any existing file (with O_TRUNC) as another thread might be mapping it.
+        unlink(path.data());
+        oflag = O_RDWR | O_CREAT | O_NONBLOCK;
         mode = S_IRUSR | S_IWUSR;
         break;
     case Type::Write:
@@ -69,25 +63,30 @@ Ref<IOChannel> IOChannel::open(const String& filePath, IOChannel::Type type)
         mode = 0;
     }
 
-    CString path = WebCore::fileSystemRepresentation(filePath);
     int fd = ::open(path.data(), oflag, mode);
+    m_fileDescriptor = fd;
 
-    return adoptRef(*new IOChannel(fd));
+    m_dispatchIO = adoptDispatch(dispatch_io_create(DISPATCH_IO_RANDOM, fd, dispatch_get_main_queue(), [fd](int) {
+        close(fd);
+    }));
+    ASSERT(m_dispatchIO.get());
+    // This makes the channel read/write all data before invoking the handlers.
+    dispatch_io_set_low_water(m_dispatchIO.get(), std::numeric_limits<size_t>::max());
+}
+
+Ref<IOChannel> IOChannel::open(const String& filePath, IOChannel::Type type)
+{
+    return adoptRef(*new IOChannel(filePath, type));
 }
 
-void IOChannel::read(size_t offset, size_t size, std::function<void ( Data&, int error)> completionHandler)
+void IOChannel::read(size_t offset, size_t size, std::function<void (Data&, int error)> completionHandler)
 {
     RefPtr<IOChannel> channel(this);
     bool didCallCompletionHandler = false;
     dispatch_io_read(m_dispatchIO.get(), offset, size, dispatch_get_main_queue(), [channel, completionHandler, didCallCompletionHandler](bool done, dispatch_data_t fileData, int error) mutable {
-        if (done) {
-            if (!didCallCompletionHandler) {
-                Data nullData;
-                completionHandler(nullData, error);
-            }
+        ASSERT_UNUSED(done, done || !didCallCompletionHandler);
+        if (didCallCompletionHandler)
             return;
-        }
-        ASSERT(!didCallCompletionHandler);
         DispatchPtr<dispatch_data_t> fileDataPtr(fileData);
         Data data(fileDataPtr);
         completionHandler(data, error);
@@ -95,6 +94,17 @@ void IOChannel::read(size_t offset, size_t size, std::function<void ( Data&, int
     });
 }
 
+// FIXME: It would be better to do without this.
+void IOChannel::readSync(size_t offset, size_t size, std::function<void (Data&, int error)> completionHandler)
+{
+    auto semaphore = adoptDispatch(dispatch_semaphore_create(0));
+    read(offset, size, [semaphore, &completionHandler](Data& data, int error) {
+        completionHandler(data, error);
+        dispatch_semaphore_signal(semaphore.get());
+    });
+    dispatch_semaphore_wait(semaphore.get(), DISPATCH_TIME_FOREVER);
+}
+
 void IOChannel::write(size_t offset, const Data& data, std::function<void (int error)> completionHandler)
 {
     RefPtr<IOChannel> channel(this);