Title: [284695] trunk/Source/WebKit
Revision
284695
Author
[email protected]
Date
2021-10-22 11:09:11 -0700 (Fri, 22 Oct 2021)

Log Message

RemoteRenderingBackend::CreateImageBuffer should be an async IPC stream message
https://bugs.webkit.org/show_bug.cgi?id=231970

Reviewed by Kimmo Kinnunen.

This patch reverts the changes in r284476, which worked around a race when adding receive queues for newly
created IPC stream destinations and simultaneously dispatching IPC messages to those destinations. Rather than
making the IPC message that creates and adds the new image buffer's RemoteDisplayListRecorder synchronous, we
instead keep that message async and make adjustments to ensure that incoming out-of-stream IPC messages for
RemoteDisplayListRecorder can always be mapped to an appropriate receive queue. See below for more details.

* GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
(WebKit::RemoteDisplayListRecorder::startListeningForIPC):

Move the main runloop bounce down to `StreamServerConnectionBase::startReceivingMessagesImpl()` instead (to deal
with the fact that `addMessageReceiveQueue` currently needs to be invoked on the main runloop). This allows us
to call `StreamServerConnection::startReceivingMessages()` from the processing queue while creating a remote
image buffer, which (in turn) ensures that incoming out-of-stream messages from the IPC thread will be sent to
the correct RemoteDisplayListRecorder destination by the time they're dispatched on the work queue thread.

* GPUProcess/graphics/RemoteRenderingBackend.cpp:
(WebKit::RemoteRenderingBackend::startListeningForIPC):
(WebKit::RemoteRenderingBackend::stopListeningForIPC):

Additionally register a "0-destination" receiver to ensure that all RemoteDisplayListRecorder messages (even
without pre-existing destinations) will be enqueued on the same IPC stream connection as this remote rendering
backend.

(WebKit::RemoteRenderingBackend::createImageBuffer):
* GPUProcess/graphics/RemoteRenderingBackend.h:
* GPUProcess/graphics/RemoteRenderingBackend.messages.in:

Make `CreateImageBuffer` an async stream message once again.

* Platform/IPC/StreamConnectionWorkQueue.cpp:
(IPC::StreamConnectionWorkQueue::processStreams):
* Platform/IPC/StreamConnectionWorkQueue.h:

Change `m_connections` into a HashCountedSet (from a HashSet), to ensure that the same server connection object
can be added to and removed from the work queue multiple times, without removing the connection from the map
early.

* Platform/IPC/StreamServerConnection.cpp:
(IPC::StreamServerConnectionBase::startReceivingMessagesImpl):
(IPC::StreamServerConnectionBase::stopReceivingMessagesImpl):
* Platform/IPC/StreamServerConnection.h:
(IPC::StreamServerConnection::startReceivingMessages):
(IPC::StreamServerConnection::stopReceivingMessages):

Add new methods to start and stop receiving all messages for a given ReceiverName, regardless of incoming
destination ID. RemoteRenderingBackend now uses this to register a "catch-all" listener for all
RemoteDisplayListRecorder messages.

* WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
(WebKit::RemoteRenderingBackendProxy::createRemoteImageBuffer):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (284694 => 284695)


--- trunk/Source/WebKit/ChangeLog	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/ChangeLog	2021-10-22 18:09:11 UTC (rev 284695)
@@ -1,3 +1,61 @@
+2021-10-22  Wenson Hsieh  <[email protected]>
+
+        RemoteRenderingBackend::CreateImageBuffer should be an async IPC stream message
+        https://bugs.webkit.org/show_bug.cgi?id=231970
+
+        Reviewed by Kimmo Kinnunen.
+
+        This patch reverts the changes in r284476, which worked around a race when adding receive queues for newly
+        created IPC stream destinations and simultaneously dispatching IPC messages to those destinations. Rather than
+        making the IPC message that creates and adds the new image buffer's RemoteDisplayListRecorder synchronous, we
+        instead keep that message async and make adjustments to ensure that incoming out-of-stream IPC messages for
+        RemoteDisplayListRecorder can always be mapped to an appropriate receive queue. See below for more details.
+
+        * GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
+        (WebKit::RemoteDisplayListRecorder::startListeningForIPC):
+
+        Move the main runloop bounce down to `StreamServerConnectionBase::startReceivingMessagesImpl()` instead (to deal
+        with the fact that `addMessageReceiveQueue` currently needs to be invoked on the main runloop). This allows us
+        to call `StreamServerConnection::startReceivingMessages()` from the processing queue while creating a remote
+        image buffer, which (in turn) ensures that incoming out-of-stream messages from the IPC thread will be sent to
+        the correct RemoteDisplayListRecorder destination by the time they're dispatched on the work queue thread.
+
+        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
+        (WebKit::RemoteRenderingBackend::startListeningForIPC):
+        (WebKit::RemoteRenderingBackend::stopListeningForIPC):
+
+        Additionally register a "0-destination" receiver to ensure that all RemoteDisplayListRecorder messages (even
+        without pre-existing destinations) will be enqueued on the same IPC stream connection as this remote rendering
+        backend.
+
+        (WebKit::RemoteRenderingBackend::createImageBuffer):
+        * GPUProcess/graphics/RemoteRenderingBackend.h:
+        * GPUProcess/graphics/RemoteRenderingBackend.messages.in:
+
+        Make `CreateImageBuffer` an async stream message once again.
+
+        * Platform/IPC/StreamConnectionWorkQueue.cpp:
+        (IPC::StreamConnectionWorkQueue::processStreams):
+        * Platform/IPC/StreamConnectionWorkQueue.h:
+
+        Change `m_connections` into a HashCountedSet (from a HashSet), to ensure that the same server connection object
+        can be added to and removed from the work queue multiple times, without removing the connection from the map
+        early.
+
+        * Platform/IPC/StreamServerConnection.cpp:
+        (IPC::StreamServerConnectionBase::startReceivingMessagesImpl):
+        (IPC::StreamServerConnectionBase::stopReceivingMessagesImpl):
+        * Platform/IPC/StreamServerConnection.h:
+        (IPC::StreamServerConnection::startReceivingMessages):
+        (IPC::StreamServerConnection::stopReceivingMessages):
+
+        Add new methods to start and stop receiving all messages for a given ReceiverName, regardless of incoming
+        destination ID. RemoteRenderingBackend now uses this to register a "catch-all" listener for all
+        RemoteDisplayListRecorder messages.
+
+        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
+        (WebKit::RemoteRenderingBackendProxy::createRemoteImageBuffer):
+
 2021-10-22  Sihui Liu  <[email protected]>
 
         Followup to r284652: ensure file handle is closed in web process

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp (284694 => 284695)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp	2021-10-22 18:09:11 UTC (rev 284695)
@@ -55,10 +55,7 @@
 {
     ASSERT(!m_isListeningForIPC);
     m_isListeningForIPC = true;
-    // FIXME: Can we avoid synchronous dispatch here by adjusting the assertion in `Connection::enqueueMatchingMessagesToMessageReceiveQueue`?
-    callOnMainRunLoopAndWait([&] {
-        m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
-    });
+    m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
 }
 
 void RemoteDisplayListRecorder::stopListeningForIPC()

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (284694 => 284695)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-10-22 18:09:11 UTC (rev 284695)
@@ -92,6 +92,10 @@
 void RemoteRenderingBackend::startListeningForIPC()
 {
     m_streamConnection->startReceivingMessages(*this, Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
+    // RemoteDisplayListRecorder messages depend on RemoteRenderingBackend, because RemoteRenderingBackend creates RemoteDisplayListRecorder and
+    // makes a receive queue for it. In order to guarantee correct ordering, ensure that all RemoteDisplayListRecorder messages are processed in
+    // the same sequence as RemoteRenderingBackend messages.
+    m_streamConnection->startReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
 }
 
 RemoteRenderingBackend::~RemoteRenderingBackend()
@@ -106,6 +110,7 @@
 {
     ASSERT(RunLoop::isMain());
     m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
+    m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
     for (auto& remoteContext : std::exchange(m_remoteDisplayLists, { }))
         remoteContext.stopListeningForIPC();
 }
@@ -138,12 +143,11 @@
     send(Messages::RemoteRenderingBackendProxy::DidFlush(flushIdentifier, renderingResourceIdentifier.object()), m_renderingBackendIdentifier);
 }
 
-void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferResourceIdentifier, CompletionHandler<void()>&& completionHandler)
+void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferResourceIdentifier)
 {
     // Immediately turn the RenderingResourceIdentifier (which is error-prone) to a QualifiedRenderingResourceIdentifier,
     // and use a helper function to make sure that don't accidentally use the RenderingResourceIdentifier (because the helper function can't see it).
     createImageBufferWithQualifiedIdentifier(logicalSize, renderingMode, resolutionScale, colorSpace, pixelFormat, { imageBufferResourceIdentifier, m_gpuConnectionToWebProcess->webProcessIdentifier() });
-    completionHandler();
 }
 
 void RemoteRenderingBackend::createImageBufferWithQualifiedIdentifier(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, QualifiedRenderingResourceIdentifier imageBufferResourceIdentifier)

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h (284694 => 284695)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2021-10-22 18:09:11 UTC (rev 284695)
@@ -101,7 +101,7 @@
     uint64_t messageSenderDestinationID() const override;
 
     // Messages to be received.
-    void createImageBuffer(const WebCore::FloatSize& logicalSize, WebCore::RenderingMode, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingResourceIdentifier, CompletionHandler<void()>&&);
+    void createImageBuffer(const WebCore::FloatSize& logicalSize, WebCore::RenderingMode, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingResourceIdentifier);
     void updateSharedMemoryForGetPixelBuffer(uint32_t byteCount, CompletionHandler<void(const SharedMemory::IPCHandle&)>&&);
     void semaphoreForGetPixelBuffer(CompletionHandler<void(const IPC::Semaphore&)>&&);
     void updateSharedMemoryAndSemaphoreForGetPixelBuffer(uint32_t byteCount, CompletionHandler<void(const SharedMemory::IPCHandle&, const IPC::Semaphore&)>&&);

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in (284694 => 284695)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in	2021-10-22 18:09:11 UTC (rev 284695)
@@ -23,7 +23,7 @@
 #if ENABLE(GPU_PROCESS)
 
 messages -> RemoteRenderingBackend NotRefCounted Stream {
-    CreateImageBuffer(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::DestinationColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat, WebCore::RenderingResourceIdentifier renderingResourceIdentifier) -> () Synchronous
+    CreateImageBuffer(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::DestinationColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat, WebCore::RenderingResourceIdentifier renderingResourceIdentifier)
     UpdateSharedMemoryForGetPixelBuffer(uint32_t byteCount) -> (WebKit::SharedMemory::IPCHandle handle) Synchronous NotStreamEncodableReply
     SemaphoreForGetPixelBuffer() -> (IPC::Semaphore semaphore) Synchronous NotStreamEncodableReply
     UpdateSharedMemoryAndSemaphoreForGetPixelBuffer(uint32_t byteCount) -> (WebKit::SharedMemory::IPCHandle handle, IPC::Semaphore semaphore) Synchronous NotStreamEncodableReply

Modified: trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.cpp (284694 => 284695)


--- trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.cpp	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.cpp	2021-10-22 18:09:11 UTC (rev 284695)
@@ -121,11 +121,11 @@
     bool hasMoreToProcess = false;
     do {
         Deque<WTF::Function<void()>> functions;
-        HashSet<Ref<StreamServerConnectionBase>> connections;
+        Vector<Ref<StreamServerConnectionBase>> connections;
         {
             Locker locker { m_lock };
             functions.swap(m_functions);
-            connections = m_connections;
+            connections = copyToVector(m_connections.values());
         }
         for (auto& function : functions)
             WTFMove(function)();

Modified: trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.h (284694 => 284695)


--- trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.h	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.h	2021-10-22 18:09:11 UTC (rev 284695)
@@ -30,7 +30,7 @@
 #include <atomic>
 #include <wtf/Deque.h>
 #include <wtf/FunctionDispatcher.h>
-#include <wtf/HashSet.h>
+#include <wtf/HashCountedSet.h>
 #include <wtf/Lock.h>
 #include <wtf/Threading.h>
 
@@ -66,7 +66,7 @@
     Lock m_lock;
     RefPtr<Thread> m_processingThread WTF_GUARDED_BY_LOCK(m_lock);
     Deque<Function<void()>> m_functions WTF_GUARDED_BY_LOCK(m_lock);
-    HashSet<Ref<StreamServerConnectionBase>> m_connections WTF_GUARDED_BY_LOCK(m_lock);
+    HashCountedSet<Ref<StreamServerConnectionBase>> m_connections WTF_GUARDED_BY_LOCK(m_lock);
 };
 
 }

Modified: trunk/Source/WebKit/Platform/IPC/StreamServerConnection.cpp (284694 => 284695)


--- trunk/Source/WebKit/Platform/IPC/StreamServerConnection.cpp	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/Platform/IPC/StreamServerConnection.cpp	2021-10-22 18:09:11 UTC (rev 284695)
@@ -40,10 +40,27 @@
 
 void StreamServerConnectionBase::startReceivingMessagesImpl(ReceiverName receiverName, uint64_t destinationID)
 {
-    m_connection->addMessageReceiveQueue(*this, receiverName, destinationID);
+    // FIXME: Can we avoid synchronous dispatch here by adjusting the assertion in `Connection::enqueueMatchingMessagesToMessageReceiveQueue`?
+    callOnMainRunLoopAndWait([&] {
+        m_connection->addMessageReceiveQueue(*this, receiverName, destinationID);
+    });
     m_workQueue.addStreamConnection(*this);
 }
 
+void StreamServerConnectionBase::startReceivingMessagesImpl(ReceiverName receiverName)
+{
+    callOnMainRunLoopAndWait([&] {
+        m_connection->addMessageReceiveQueue(*this, receiverName);
+    });
+    m_workQueue.addStreamConnection(*this);
+}
+
+void StreamServerConnectionBase::stopReceivingMessagesImpl(ReceiverName receiverName)
+{
+    m_connection->removeMessageReceiveQueue(receiverName);
+    m_workQueue.removeStreamConnection(*this);
+}
+
 void StreamServerConnectionBase::stopReceivingMessagesImpl(ReceiverName receiverName, uint64_t destinationID)
 {
     m_connection->removeMessageReceiveQueue(receiverName, destinationID);

Modified: trunk/Source/WebKit/Platform/IPC/StreamServerConnection.h (284694 => 284695)


--- trunk/Source/WebKit/Platform/IPC/StreamServerConnection.h	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/Platform/IPC/StreamServerConnection.h	2021-10-22 18:09:11 UTC (rev 284695)
@@ -62,6 +62,9 @@
     void startReceivingMessagesImpl(ReceiverName, uint64_t destinationID);
     void stopReceivingMessagesImpl(ReceiverName, uint64_t destinationID);
 
+    void startReceivingMessagesImpl(ReceiverName);
+    void stopReceivingMessagesImpl(ReceiverName);
+
     // MessageReceiveQueue
     void enqueueMessage(Connection&, std::unique_ptr<Decoder>&&) final;
 
@@ -144,6 +147,9 @@
     // Stops the message receipt. Note: already received messages might still be delivered.
     void stopReceivingMessages(ReceiverName, uint64_t destinationID);
 
+    inline void startReceivingMessages(ReceiverName);
+    inline void stopReceivingMessages(ReceiverName);
+
     // StreamServerConnectionBase overrides.
     DispatchResult dispatchStreamMessages(size_t messageLimit) final;
 
@@ -161,4 +167,14 @@
     uint64_t m_currentDestinationID { 0 };
 };
 
+void StreamServerConnection::startReceivingMessages(ReceiverName receiverName)
+{
+    StreamServerConnectionBase::startReceivingMessagesImpl(receiverName);
 }
+
+void StreamServerConnection::stopReceivingMessages(ReceiverName receiverName)
+{
+    StreamServerConnectionBase::stopReceivingMessagesImpl(receiverName);
+}
+
+}

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp (284694 => 284695)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2021-10-22 18:03:34 UTC (rev 284694)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2021-10-22 18:09:11 UTC (rev 284695)
@@ -127,9 +127,7 @@
 
 void RemoteRenderingBackendProxy::createRemoteImageBuffer(ImageBuffer& imageBuffer)
 {
-    // FIXME: This should be an normal (async) stream message. However, doing so may cause subsequent out-of-stream messages sent to the newly created image
-    // buffer to be dropped by the IPC connection. For the time being, work around this by using sync IPC (see <https://webkit.org/b/231681> for more details).
-    sendSyncToStream(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.logicalSize(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), imageBuffer.renderingResourceIdentifier()), Messages::RemoteRenderingBackend::CreateImageBuffer::Reply(), 3_s);
+    sendToStream(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.logicalSize(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), imageBuffer.renderingResourceIdentifier()));
 }
 
 RefPtr<ImageBuffer> RemoteRenderingBackendProxy::createImageBuffer(const FloatSize& size, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to