Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: a7ea563d0fb8b73b316aefd556610de241ab8d62
      
https://github.com/WebKit/WebKit/commit/a7ea563d0fb8b73b316aefd556610de241ab8d62
  Author: Rupin Mittal <[email protected]>
  Date:   2026-06-16 (Tue, 16 Jun 2026)

  Changed paths:
    M Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h
    M Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.cpp
    M Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.h

  Log Message:
  -----------
  StabilityTracer: Crash in WebKit::RemoteAudioVideoRendererProxyManager::ref
https://bugs.webkit.org/show_bug.cgi?id=317038
rdar://167378009

Reviewed by Chris Dumez.

It looks like RemoteAudioVideoRendererProxyManager::ref() crashes when
dereferencing the result of m_gpuConnectionToWebProcess.get() because it's null.

>From the crash trace, this call to ref() comes from the lambda given to
setTimeObserver() in RemoteAudioVideoRendererProxyManager::installTimeObserver()
where we initialize protectedThis.

So somehow, at the point when this lambda is called, the ThreadSafeWeakPtr that
points to the GPUConnectionWebProcess has a ref-count of zero, but the
RemoteAudioVideoRendererProxyManager that it holds is still alive (we know this
because otherwise RefPtr protectedThis would have been constructed with nullptr
and would not have called ref() at all). Since 
RemoteAudioVideoRendererProxyManager
is a unique_ptr member of GPUConnectionWebProcess, this means that the
GPUConnectionWebProcess itself hasn't been destroyed yet.

What's happening is that this lambda is called in between the 
GPUConnectionWebProcess
hitting a ref-count of zero and it's destructor being called. The ref-count can
hit zero on any thread, but the destructor must run on the main thread. So if 
the
ref-count hits zero on a non-main thread, we must hop to the main thread to
destroy it. This is asynchronous, and so there's a gap in which other code can
execute--like this lambda.

There actually is a way for us to check in the lambda whether the ref-count has
dropped to zero. GPUConnectionWebProcess inherits from
ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr, and as soon as the ref-count
drops to zero, the control block swaps its pointer to GPUConnectionWebProcess
to nullptr. So if you make a ThreadSafeWeakPtr<GPUConnectionWebProcess> weakThis
and then try weakThis.get() after the ref-count has dropped to zero, you get 
back
nullptr (even if ~GPUConnectionWebProcess() hasn't been called yet).

Given that RemoteAudioVideoRendererProxyManager's lifetime is meant to be tied
to the GPUConnectionWebProcess, we can add a controlBlock() function to
RemoteAudioVideoRendererProxyManager which simply returns the controlBlock of
GPUConnectionWebProcess. This way, we can make a ThreadSafeWeakPtr of the
RemoteAudioVideoRendererProxyManager which will return a nullptr on get() if the
GPUConnectionWebProcess has hit a ref-count of zero. We then update all of the
lambdas that were capturing weakThis to use this ThreadSafeWeakPtr. Now, if
the lambda is called in between the GPUConnectionWebProcess hitting a ref-count
of zero and actually being destroyed, weakThis.get() will see that m_object is
null and return nullptr without caling 
RemoteAudioVideoRendererProxyManager::ref()
at all.

Also, given that RemoteAudioVideoRendererProxyManager's lifetime is tied to that
of GPUConnectionWebProcess, we change m_gpuConnectionToWebProcess to be a
ThreadSafeWeakRef. Even though m_gpuConnectionToWebProcess was null in this 
case,
it should never be null after this fix.

* Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h:
* Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.cpp:
(WebKit::RemoteAudioVideoRendererProxyManager::controlBlock const):
(WebKit::RemoteAudioVideoRendererProxyManager::sharedPreferencesForWebProcess 
const):
(WebKit::RemoteAudioVideoRendererProxyManager::create):
(WebKit::RemoteAudioVideoRendererProxyManager::addTrack):
(WebKit::RemoteAudioVideoRendererProxyManager::requestMediaDataWhenReady):
(WebKit::RemoteAudioVideoRendererProxyManager::performTaskAtTime):
(WebKit::RemoteAudioVideoRendererProxyManager::installTimeObserver):
(WebKit::RemoteAudioVideoRendererProxyManager::prepareToSeek):
(WebKit::RemoteAudioVideoRendererProxyManager::finishSeek):
(WebKit::RemoteAudioVideoRendererProxyManager::notifyWhenHasAvailableVideoFrame):
* Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.h:

Canonical link: https://commits.webkit.org/315283@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to