Title: [269046] trunk
Revision
269046
Author
[email protected]
Date
2020-10-27 10:08:50 -0700 (Tue, 27 Oct 2020)

Log Message

[GLIB] imported/w3c/web-platform-tests/html/canvas/offscreen/line-styles/2d.line.width.transformed.html is a flaky crash
https://bugs.webkit.org/show_bug.cgi?id=217986

Reviewed by Simon Fraser.

Fix race condition caused by use of OffscreenCanvas::scriptExecutionContext() on main thread.
Instead of passing a reference to the OffscreenCanvas object when dealing with the placeholder
canvas on the main thread, encapsulate the necessary data in a separate, ThreadSafeRefCounted
object and pass that instead, negating the need to call back to the Worker thread to release
the reference.

Covered by existing tests.

* html/OffscreenCanvas.cpp:
(WebCore::OffscreenCanvas::create):
(WebCore::OffscreenCanvas::OffscreenCanvas):
(WebCore::OffscreenCanvas::detach):
(WebCore::OffscreenCanvas::setPlaceholderCanvas):
(WebCore::OffscreenCanvas::pushBufferToPlaceholder):
(WebCore::OffscreenCanvas::commitToPlaceholderCanvas):
* html/OffscreenCanvas.h:

Modified Paths

Diff

Modified: trunk/LayoutTests/platform/glib/TestExpectations (269045 => 269046)


--- trunk/LayoutTests/platform/glib/TestExpectations	2020-10-27 16:58:03 UTC (rev 269045)
+++ trunk/LayoutTests/platform/glib/TestExpectations	2020-10-27 17:08:50 UTC (rev 269046)
@@ -392,11 +392,6 @@
 
 webkit.org/b/215462 imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.html [ Failure Pass ]
 
-# Flaky crash on pushBufferToPlaceholder().
-webkit.org/b/217986 imported/w3c/web-platform-tests/html/canvas/offscreen/line-styles/2d.line.width.transformed.html [ Crash Pass ]
-webkit.org/b/217986 imported/w3c/web-platform-tests/html/canvas/offscreen/path-objects/2d.path.arc.selfintersect.1.worker.html [ Crash Pass ]
-webkit.org/b/217986 imported/w3c/web-platform-tests/html/canvas/offscreen/path-objects/2d.path.arc.selfintersect.1.html [ Crash Pass ]
-
 #////////////////////////////////////////////////////////////////////////////////////////
 # End of OffscreenCanvas-related bugs
 #////////////////////////////////////////////////////////////////////////////////////////

Modified: trunk/Source/WebCore/ChangeLog (269045 => 269046)


--- trunk/Source/WebCore/ChangeLog	2020-10-27 16:58:03 UTC (rev 269045)
+++ trunk/Source/WebCore/ChangeLog	2020-10-27 17:08:50 UTC (rev 269046)
@@ -1,3 +1,27 @@
+2020-10-27  Chris Lord  <[email protected]>
+
+        [GLIB] imported/w3c/web-platform-tests/html/canvas/offscreen/line-styles/2d.line.width.transformed.html is a flaky crash
+        https://bugs.webkit.org/show_bug.cgi?id=217986
+
+        Reviewed by Simon Fraser.
+
+        Fix race condition caused by use of OffscreenCanvas::scriptExecutionContext() on main thread.
+        Instead of passing a reference to the OffscreenCanvas object when dealing with the placeholder
+        canvas on the main thread, encapsulate the necessary data in a separate, ThreadSafeRefCounted
+        object and pass that instead, negating the need to call back to the Worker thread to release
+        the reference.
+
+        Covered by existing tests.
+
+        * html/OffscreenCanvas.cpp:
+        (WebCore::OffscreenCanvas::create):
+        (WebCore::OffscreenCanvas::OffscreenCanvas):
+        (WebCore::OffscreenCanvas::detach):
+        (WebCore::OffscreenCanvas::setPlaceholderCanvas):
+        (WebCore::OffscreenCanvas::pushBufferToPlaceholder):
+        (WebCore::OffscreenCanvas::commitToPlaceholderCanvas):
+        * html/OffscreenCanvas.h:
+
 2020-10-27  Antti Koivisto  <[email protected]>
 
         [LFC][Integration] Use iterator for next/previousLinePosition

Modified: trunk/Source/WebCore/html/OffscreenCanvas.cpp (269045 => 269046)


--- trunk/Source/WebCore/html/OffscreenCanvas.cpp	2020-10-27 16:58:03 UTC (rev 269045)
+++ trunk/Source/WebCore/html/OffscreenCanvas.cpp	2020-10-27 17:08:50 UTC (rev 269046)
@@ -85,16 +85,14 @@
     if (!detachedCanvas->originClean())
         clone->setOriginTainted();
 
-    callOnMainThread([detachedCanvas = WTFMove(detachedCanvas), offscreenCanvas = makeRef(clone.get())] () mutable {
-        offscreenCanvas->m_placeholderCanvas = detachedCanvas->takePlaceholderCanvas();
-        if (offscreenCanvas->m_placeholderCanvas) {
-            auto& placeholderContext = downcast<PlaceholderRenderingContext>(*offscreenCanvas->m_placeholderCanvas->renderingContext());
+    callOnMainThread([detachedCanvas = WTFMove(detachedCanvas), placeholderData = makeRef(*clone->m_placeholderData)] () mutable {
+        placeholderData->canvas = detachedCanvas->takePlaceholderCanvas();
+        if (placeholderData->canvas) {
+            auto& placeholderContext = downcast<PlaceholderRenderingContext>(*placeholderData->canvas->renderingContext());
             auto& imageBufferPipe = placeholderContext.imageBufferPipe();
             if (imageBufferPipe)
-                offscreenCanvas->m_bufferPipeSource = imageBufferPipe->source();
+                placeholderData->bufferPipeSource = imageBufferPipe->source();
         }
-        offscreenCanvas->scriptExecutionContext()->postTask({ ScriptExecutionContext::Task::CleanupTask,
-            [releaseOffscreenCanvas = WTFMove(offscreenCanvas)] (ScriptExecutionContext&) { } });
     });
 
     return clone;
@@ -110,6 +108,7 @@
 OffscreenCanvas::OffscreenCanvas(ScriptExecutionContext& context, unsigned width, unsigned height)
     : CanvasBase(IntSize(width, height))
     , ContextDestructionObserver(&context)
+    , m_placeholderData(PlaceholderData::create())
 {
 }
 
@@ -389,7 +388,7 @@
     m_detached = true;
 
     auto detached = makeUnique<DetachedOffscreenCanvas>(takeImageBuffer(), size(), originClean());
-    detached->m_placeholderCanvas = std::exchange(m_placeholderCanvas, nullptr);
+    detached->m_placeholderCanvas = std::exchange(m_placeholderData->canvas, nullptr);
 
     return detached;
 }
@@ -398,25 +397,20 @@
 {
     ASSERT(!m_context);
     ASSERT(isMainThread());
-    m_placeholderCanvas = makeWeakPtr(canvas);
+    m_placeholderData->canvas = makeWeakPtr(canvas);
     auto& placeholderContext = downcast<PlaceholderRenderingContext>(*canvas.renderingContext());
     auto& imageBufferPipe = placeholderContext.imageBufferPipe();
     if (imageBufferPipe)
-        m_bufferPipeSource = imageBufferPipe->source();
+        m_placeholderData->bufferPipeSource = imageBufferPipe->source();
 }
 
 void OffscreenCanvas::pushBufferToPlaceholder()
 {
-    callOnMainThread([protectedThis = makeRef(*this), this] () mutable {
-        {
-            auto locker = holdLock(m_commitLock);
-            if (m_placeholderCanvas && m_pendingCommitBuffer)
-                m_placeholderCanvas->setImageBufferAndMarkDirty(WTFMove(m_pendingCommitBuffer));
-            m_pendingCommitBuffer = nullptr;
-        }
-
-        scriptExecutionContext()->postTask({ ScriptExecutionContext::Task::CleanupTask,
-            [releaseThis = WTFMove(protectedThis)] (ScriptExecutionContext&) { } });
+    callOnMainThread([placeholderData = makeRef(*m_placeholderData)] () mutable {
+        auto locker = holdLock(placeholderData->bufferLock);
+        if (placeholderData->canvas && placeholderData->pendingCommitBuffer)
+            placeholderData->canvas->setImageBufferAndMarkDirty(WTFMove(placeholderData->pendingCommitBuffer));
+        placeholderData->pendingCommitBuffer = nullptr;
     });
 }
 
@@ -430,16 +424,16 @@
     if (m_context && (m_context->isWebGL() || m_context->isAccelerated()))
         m_context->paintRenderingResultsToCanvas();
 
-    if (m_bufferPipeSource) {
+    if (m_placeholderData->bufferPipeSource) {
         auto bufferCopy = imageBuffer->copyRectToBuffer(FloatRect(FloatPoint(), imageBuffer->logicalSize()), ColorSpace::SRGB, imageBuffer->context());
         if (bufferCopy)
-            m_bufferPipeSource->handle(WTFMove(bufferCopy));
+            m_placeholderData->bufferPipeSource->handle(WTFMove(bufferCopy));
     }
 
-    auto locker = holdLock(m_commitLock);
-    bool shouldPushBuffer = !m_pendingCommitBuffer;
-    m_pendingCommitBuffer = imageBuffer->copyRectToBuffer(FloatRect(FloatPoint(), imageBuffer->logicalSize()), ColorSpace::SRGB, imageBuffer->context());
-    if (m_pendingCommitBuffer && shouldPushBuffer)
+    auto locker = holdLock(m_placeholderData->bufferLock);
+    bool shouldPushBuffer = !m_placeholderData->pendingCommitBuffer;
+    m_placeholderData->pendingCommitBuffer = imageBuffer->copyRectToBuffer(FloatRect(FloatPoint(), imageBuffer->logicalSize()), ColorSpace::SRGB, imageBuffer->context());
+    if (m_placeholderData->pendingCommitBuffer && shouldPushBuffer)
         pushBufferToPlaceholder();
 }
 

Modified: trunk/Source/WebCore/html/OffscreenCanvas.h (269045 => 269046)


--- trunk/Source/WebCore/html/OffscreenCanvas.h	2020-10-27 16:58:03 UTC (rev 269045)
+++ trunk/Source/WebCore/html/OffscreenCanvas.h	2020-10-27 17:08:50 UTC (rev 269046)
@@ -39,6 +39,7 @@
 #include "ScriptWrappable.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 #if ENABLE(WEBGL)
@@ -187,11 +188,21 @@
     mutable RefPtr<Image> m_copiedImage;
 
     bool m_hasScheduledCommit { false };
-    WeakPtr<HTMLCanvasElement> m_placeholderCanvas;
-    RefPtr<ImageBufferPipe::Source> m_bufferPipeSource;
 
-    mutable Lock m_commitLock;
-    std::unique_ptr<ImageBuffer> m_pendingCommitBuffer;
+    class PlaceholderData : public ThreadSafeRefCounted<PlaceholderData> {
+    public:
+        static Ref<PlaceholderData> create()
+        {
+            return adoptRef(*new PlaceholderData);
+        }
+
+        WeakPtr<HTMLCanvasElement> canvas;
+        RefPtr<ImageBufferPipe::Source> bufferPipeSource;
+        std::unique_ptr<ImageBuffer> pendingCommitBuffer;
+        mutable Lock bufferLock;
+    };
+
+    RefPtr<PlaceholderData> m_placeholderData;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to