⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 284768 in webkit


Ignore:
Timestamp:
Oct 24, 2021, 1:57:44 PM (5 years ago)
Author:
Wenson Hsieh
Message:

RemoteRenderingBackend should not send IPC in the middle of destruction
https://bugs.webkit.org/show_bug.cgi?id=232179

Reviewed by Darin Adler.

Make a couple of minor adjustments to RemoteRenderingBackend (see below for more details). This is necessary in
order to avoid flaky crashes after fixing bug #232113, after which the RemoteRenderingBackend will no longer be
leaked in the GPU process.

  • GPUProcess/graphics/RemoteRenderingBackend.cpp:

(WebKit::RemoteRenderingBackend::startListeningForIPC):
(WebKit::RemoteRenderingBackend::stopListeningForIPC):
(WebKit::RemoteRenderingBackend::didCreateImageBufferBackend):
(WebKit::RemoteRenderingBackend::releaseRemoteResourceWithQualifiedIdentifier):
(WebKit::RemoteRenderingBackend::~RemoteRenderingBackend): Deleted.

Move logic to flush remaining incoming IPC messages in the GPU process out of the destructor, and into
stopListeningForIPC() instead. This is because the act of processing certain stream IPC messages (such as
CreateImageBuffer or FlushContext) may cause RemoteRenderingBackend to try and send IPC back to the web process.
However, if RemoteRenderingBackend is in the middle of destruction, it will crash when attempting to do so (when
attempting to call into IPC::MessageSender).

To avoid this, we need to do this work earlier, after we've already stopped listening for further IPC messages.

  • GPUProcess/graphics/RemoteRenderingBackend.h:

Turn m_remoteDisplayLists into a regular hash map containing RemoteDisplayListRecorders by their process-
qualified rendering resource identifiers. Since this map may be modified from different threads, we (1) don't
want to be using weak pointers here, and (2) need to ensure that access to this table is guarded behind a lock.
To avoid reference cycles, entries in this table are cleared out when the remote image buffer corresponding to
each RemoteDisplayListRecorder is released in the GPU process.

Location:
trunk/Source/WebKit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r284766 r284768  
     12021-10-24  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        RemoteRenderingBackend should not send IPC in the middle of destruction
     4        https://bugs.webkit.org/show_bug.cgi?id=232179
     5
     6        Reviewed by Darin Adler.
     7
     8        Make a couple of minor adjustments to RemoteRenderingBackend (see below for more details). This is necessary in
     9        order to avoid flaky crashes after fixing bug #232113, after which the RemoteRenderingBackend will no longer be
     10        leaked in the GPU process.
     11
     12        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
     13        (WebKit::RemoteRenderingBackend::startListeningForIPC):
     14        (WebKit::RemoteRenderingBackend::stopListeningForIPC):
     15        (WebKit::RemoteRenderingBackend::didCreateImageBufferBackend):
     16        (WebKit::RemoteRenderingBackend::releaseRemoteResourceWithQualifiedIdentifier):
     17        (WebKit::RemoteRenderingBackend::~RemoteRenderingBackend): Deleted.
     18
     19        Move logic to flush remaining incoming IPC messages in the GPU process out of the destructor, and into
     20        `stopListeningForIPC()` instead. This is because the act of processing certain stream IPC messages (such as
     21        CreateImageBuffer or FlushContext) may cause RemoteRenderingBackend to try and send IPC back to the web process.
     22        However, if RemoteRenderingBackend is in the middle of destruction, it will crash when attempting to do so (when
     23        attempting to call into IPC::MessageSender).
     24
     25        To avoid this, we need to do this work earlier, after we've already stopped listening for further IPC messages.
     26
     27        * GPUProcess/graphics/RemoteRenderingBackend.h:
     28
     29        Turn `m_remoteDisplayLists` into a regular hash map containing RemoteDisplayListRecorders by their process-
     30        qualified rendering resource identifiers. Since this map may be modified from different threads, we (1) don't
     31        want to be using weak pointers here, and (2) need to ensure that access to this table is guarded behind a lock.
     32        To avoid reference cycles, entries in this table are cleared out when the remote image buffer corresponding to
     33        each RemoteDisplayListRecorder is released in the GPU process.
     34
    1352021-10-24  Wenson Hsieh  <wenson_hsieh@apple.com>
    236
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp

    r284695 r284768  
    9090}
    9191
     92RemoteRenderingBackend::~RemoteRenderingBackend() = default;
     93
    9294void RemoteRenderingBackend::startListeningForIPC()
    9395{
     96    {
     97        Locker locker { m_remoteDisplayListsLock };
     98        m_canRegisterRemoteDisplayLists = true;
     99    }
     100
    94101    m_streamConnection->startReceivingMessages(*this, Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
    95102    // RemoteDisplayListRecorder messages depend on RemoteRenderingBackend, because RemoteRenderingBackend creates RemoteDisplayListRecorder and
     
    99106}
    100107
    101 RemoteRenderingBackend::~RemoteRenderingBackend()
    102 {
     108void RemoteRenderingBackend::stopListeningForIPC()
     109{
     110    ASSERT(RunLoop::isMain());
     111    m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
     112    m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
     113
     114    {
     115        Locker locker { m_remoteDisplayListsLock };
     116        m_canRegisterRemoteDisplayLists = false;
     117        for (auto& remoteContext : std::exchange(m_remoteDisplayLists, { }))
     118            remoteContext.value->stopListeningForIPC();
     119    }
     120
    103121    // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue.
    104122    // Make sure rendering resource request is released after destroying the cache.
     
    107125}
    108126
    109 void RemoteRenderingBackend::stopListeningForIPC()
    110 {
    111     ASSERT(RunLoop::isMain());
    112     m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
    113     m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
    114     for (auto& remoteContext : std::exchange(m_remoteDisplayLists, { }))
    115         remoteContext.stopListeningForIPC();
    116 }
    117 
    118127void RemoteRenderingBackend::dispatch(Function<void()>&& task)
    119128{
     
    133142void RemoteRenderingBackend::didCreateImageBufferBackend(ImageBufferBackendHandle handle, QualifiedRenderingResourceIdentifier renderingResourceIdentifier, RemoteDisplayListRecorder& remoteDisplayList)
    134143{
    135     m_remoteDisplayLists.add(remoteDisplayList);
     144    {
     145        Locker locker { m_remoteDisplayListsLock };
     146        if (m_canRegisterRemoteDisplayLists)
     147            m_remoteDisplayLists.add(renderingResourceIdentifier, remoteDisplayList);
     148    }
    136149    MESSAGE_CHECK(renderingResourceIdentifier.processIdentifier() == m_gpuConnectionToWebProcess->webProcessIdentifier(), "Sending didCreateImageBufferBackend() message to the wrong web process.");
    137150    send(Messages::RemoteRenderingBackendProxy::DidCreateImageBufferBackend(WTFMove(handle), renderingResourceIdentifier.object()), m_renderingBackendIdentifier);
     
    364377    MESSAGE_CHECK(success, "Resource is being released before being cached.");
    365378    updateRenderingResourceRequest();
     379
     380    Locker locker { m_remoteDisplayListsLock };
     381    m_remoteDisplayLists.remove(renderingResourceIdentifier);
    366382}
    367383
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h

    r284695 r284768  
    134134    RefPtr<SharedMemory> m_getPixelBufferSharedMemory;
    135135    ScopedRenderingResourcesRequest m_renderingResourcesRequest;
    136     WeakHashSet<RemoteDisplayListRecorder> m_remoteDisplayLists;
     136
     137    Lock m_remoteDisplayListsLock;
     138    bool m_canRegisterRemoteDisplayLists WTF_GUARDED_BY_LOCK(m_remoteDisplayListsLock) { false };
     139    HashMap<QualifiedRenderingResourceIdentifier, Ref<RemoteDisplayListRecorder>> m_remoteDisplayLists WTF_GUARDED_BY_LOCK(m_remoteDisplayListsLock);
    137140};
    138141
Note: See TracChangeset for help on using the changeset viewer.