Title: [285024] trunk/Source/WebCore
Revision
285024
Author
[email protected]
Date
2021-10-29 03:59:34 -0700 (Fri, 29 Oct 2021)

Log Message

Fix potential race in AudioMediaStreamTrackRendererCocoa::pushSamples
https://bugs.webkit.org/show_bug.cgi?id=232430

Reviewed by Eric Carlson.

In case we start a AudioMediaStreamTrackRendererCocoa, and we quickly stop it, there may be a time
where we create an AudioSampleDataSource from a background thread, then hop to main thread.
We would then register it to the rendering unit even if the AudioMediaStreamTrackRendererCocoa is cleared.
The AudioSampleDataSource would then be kept registered with no data which would be wasteful in terms of CPU.
To fix this, we keep m_dataSource but introduce a m_registeredDataSource.
m_registeredDataSource is only manipulated in main thread and is the one that is registered/unregistered to the rendering unit.
m_dataSource is only accessed from background thread.

Manually tested and covered by added assertion in AudioMediaStreamTrackRendererCocoa destructor.

* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
(WebCore::AudioMediaStreamTrackRendererCocoa::~AudioMediaStreamTrackRendererCocoa):
(WebCore::AudioMediaStreamTrackRendererCocoa::clear):
(WebCore::AudioMediaStreamTrackRendererCocoa::setRegisteredDataSource):
(WebCore::AudioMediaStreamTrackRendererCocoa::pushSamples):
(WebCore::pollSamplesCount): Deleted.
* platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (285023 => 285024)


--- trunk/Source/WebCore/ChangeLog	2021-10-29 09:50:10 UTC (rev 285023)
+++ trunk/Source/WebCore/ChangeLog	2021-10-29 10:59:34 UTC (rev 285024)
@@ -1,5 +1,30 @@
 2021-10-29  Youenn Fablet  <[email protected]>
 
+        Fix potential race in AudioMediaStreamTrackRendererCocoa::pushSamples
+        https://bugs.webkit.org/show_bug.cgi?id=232430
+
+        Reviewed by Eric Carlson.
+
+        In case we start a AudioMediaStreamTrackRendererCocoa, and we quickly stop it, there may be a time
+        where we create an AudioSampleDataSource from a background thread, then hop to main thread.
+        We would then register it to the rendering unit even if the AudioMediaStreamTrackRendererCocoa is cleared.
+        The AudioSampleDataSource would then be kept registered with no data which would be wasteful in terms of CPU.
+        To fix this, we keep m_dataSource but introduce a m_registeredDataSource.
+        m_registeredDataSource is only manipulated in main thread and is the one that is registered/unregistered to the rendering unit.
+        m_dataSource is only accessed from background thread.
+
+        Manually tested and covered by added assertion in AudioMediaStreamTrackRendererCocoa destructor.
+
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp:
+        (WebCore::AudioMediaStreamTrackRendererCocoa::~AudioMediaStreamTrackRendererCocoa):
+        (WebCore::AudioMediaStreamTrackRendererCocoa::clear):
+        (WebCore::AudioMediaStreamTrackRendererCocoa::setRegisteredDataSource):
+        (WebCore::AudioMediaStreamTrackRendererCocoa::pushSamples):
+        (WebCore::pollSamplesCount): Deleted.
+        * platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h:
+
+2021-10-29  Youenn Fablet  <[email protected]>
+
         LocalAudioMediaStreamTrackRendererInternalUnit should clip audio data
         https://bugs.webkit.org/show_bug.cgi?id=232428
 

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp (285023 => 285024)


--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp	2021-10-29 09:50:10 UTC (rev 285023)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp	2021-10-29 10:59:34 UTC (rev 285024)
@@ -41,7 +41,10 @@
 {
 }
 
-AudioMediaStreamTrackRendererCocoa::~AudioMediaStreamTrackRendererCocoa() = default;
+AudioMediaStreamTrackRendererCocoa::~AudioMediaStreamTrackRendererCocoa()
+{
+    ASSERT(!m_registeredDataSource);
+}
 
 void AudioMediaStreamTrackRendererCocoa::start(CompletionHandler<void()>&& callback)
 {
@@ -48,8 +51,10 @@
     clear();
 
     AudioMediaStreamTrackRendererUnit::singleton().retrieveFormatDescription([weakThis = WeakPtr { *this }, callback = WTFMove(callback)](auto* formatDescription) mutable {
-        if (weakThis && formatDescription)
+        if (weakThis && formatDescription) {
             weakThis->m_outputDescription = makeUnique<CAAudioStreamDescription>(*formatDescription);
+            weakThis->m_shouldRecreateDataSource = true;
+        }
         callback();
     });
 }
@@ -56,8 +61,10 @@
 
 void AudioMediaStreamTrackRendererCocoa::stop()
 {
-    if (m_dataSource)
-        AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_dataSource);
+    ASSERT(isMainThread());
+
+    if (m_registeredDataSource)
+        AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_registeredDataSource);
 }
 
 void AudioMediaStreamTrackRendererCocoa::clear()
@@ -64,21 +71,25 @@
 {
     stop();
 
-    m_dataSource = nullptr;
+    setRegisteredDataSource(nullptr);
     m_outputDescription = { };
 }
 
 void AudioMediaStreamTrackRendererCocoa::setVolume(float volume)
 {
+    ASSERT(isMainThread());
+
     AudioMediaStreamTrackRenderer::setVolume(volume);
-    if (m_dataSource)
-        m_dataSource->setVolume(volume);
+    if (m_registeredDataSource)
+        m_registeredDataSource->setVolume(volume);
 }
 
 void AudioMediaStreamTrackRendererCocoa::reset()
 {
-    if (m_dataSource)
-        m_dataSource->recomputeSampleOffset();
+    ASSERT(isMainThread());
+
+    if (m_registeredDataSource)
+        m_registeredDataSource->recomputeSampleOffset();
 }
 
 void AudioMediaStreamTrackRendererCocoa::setAudioOutputDevice(const String& deviceId)
@@ -88,6 +99,26 @@
     m_shouldRecreateDataSource = true;
 }
 
+void AudioMediaStreamTrackRendererCocoa::setRegisteredDataSource(RefPtr<AudioSampleDataSource>&& source)
+{
+    ASSERT(isMainThread());
+
+    if (m_registeredDataSource)
+        AudioMediaStreamTrackRendererUnit::singleton().removeSource(*m_registeredDataSource);
+
+    if (!m_outputDescription)
+        return;
+
+    m_registeredDataSource = WTFMove(source);
+    if (!m_registeredDataSource)
+        return;
+
+    m_registeredDataSource->setLogger(logger(), logIdentifier());
+    m_registeredDataSource->setVolume(volume());
+    AudioMediaStreamTrackRendererUnit::singleton().addResetObserver(m_resetObserver);
+    AudioMediaStreamTrackRendererUnit::singleton().addSource(*m_registeredDataSource);
+}
+
 static unsigned pollSamplesCount()
 {
 #if USE(LIBWEBRTC)
@@ -118,19 +149,9 @@
             return;
         }
 
-        callOnMainThread([this, weakThis = WeakPtr { *this }, oldSource = m_dataSource, newSource = dataSource]() mutable {
-            if (!weakThis)
-                return;
-
-#if !RELEASE_LOG_DISABLED
-            newSource->setLogger(logger(), logIdentifier());
-#endif
-            if (oldSource)
-                AudioMediaStreamTrackRendererUnit::singleton().removeSource(*oldSource);
-
-            newSource->setVolume(volume());
-            AudioMediaStreamTrackRendererUnit::singleton().addResetObserver(m_resetObserver);
-            AudioMediaStreamTrackRendererUnit::singleton().addSource(WTFMove(newSource));
+        callOnMainThread([weakThis = WeakPtr { *this }, newSource = dataSource]() mutable {
+            if (weakThis)
+                weakThis->setRegisteredDataSource(WTFMove(newSource));
         });
         m_dataSource = WTFMove(dataSource);
         m_shouldRecreateDataSource = false;

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h (285023 => 285024)


--- trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h	2021-10-29 09:50:10 UTC (rev 285023)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.h	2021-10-29 10:59:34 UTC (rev 285024)
@@ -57,9 +57,11 @@
     void setAudioOutputDevice(const String&) final;
 
     void reset();
+    void setRegisteredDataSource(RefPtr<AudioSampleDataSource>&&);
 
     std::unique_ptr<CAAudioStreamDescription> m_outputDescription;
-    RefPtr<AudioSampleDataSource> m_dataSource;
+    RefPtr<AudioSampleDataSource> m_dataSource; // Used in background thread.
+    RefPtr<AudioSampleDataSource> m_registeredDataSource; // Used in main thread.
     bool m_shouldRecreateDataSource { false };
     WebCore::AudioMediaStreamTrackRendererUnit::ResetObserver m_resetObserver;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to