Title: [214227] trunk/Source/WebCore
Revision
214227
Author
jer.no...@apple.com
Date
2017-03-21 12:45:38 -0700 (Tue, 21 Mar 2017)

Log Message

Crash in WebCore: WebCore::CARingBuffer::getCurrentFrameBounds + 28
https://bugs.webkit.org/show_bug.cgi?id=169887
<rdar://problem/23648082>

Reviewed by Eric Carlson.

Because AudioSourceProviderAVFObjC::prepareCallback() can concievably be called after the AudioSourceProviderAVFObjC
it refers to has been destroyed, add an extra layer of indirection between the tap and the provider, and invalidate
that level of indirection before the AudioSourceProviderAVFObjC is destroyed.

* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.h:
* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
(WebCore::AudioSourceProviderAVFObjC::initCallback):
(WebCore::AudioSourceProviderAVFObjC::finalizeCallback):
(WebCore::AudioSourceProviderAVFObjC::prepareCallback):
(WebCore::AudioSourceProviderAVFObjC::unprepareCallback):
(WebCore::AudioSourceProviderAVFObjC::processCallback):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (214226 => 214227)


--- trunk/Source/WebCore/ChangeLog	2017-03-21 18:18:35 UTC (rev 214226)
+++ trunk/Source/WebCore/ChangeLog	2017-03-21 19:45:38 UTC (rev 214227)
@@ -1,3 +1,23 @@
+2017-03-20  Jer Noble  <jer.no...@apple.com>
+
+        Crash in WebCore: WebCore::CARingBuffer::getCurrentFrameBounds + 28
+        https://bugs.webkit.org/show_bug.cgi?id=169887
+        <rdar://problem/23648082>
+
+        Reviewed by Eric Carlson.
+
+        Because AudioSourceProviderAVFObjC::prepareCallback() can concievably be called after the AudioSourceProviderAVFObjC
+        it refers to has been destroyed, add an extra layer of indirection between the tap and the provider, and invalidate
+        that level of indirection before the AudioSourceProviderAVFObjC is destroyed.
+
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.h:
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
+        (WebCore::AudioSourceProviderAVFObjC::initCallback):
+        (WebCore::AudioSourceProviderAVFObjC::finalizeCallback):
+        (WebCore::AudioSourceProviderAVFObjC::prepareCallback):
+        (WebCore::AudioSourceProviderAVFObjC::unprepareCallback):
+        (WebCore::AudioSourceProviderAVFObjC::processCallback):
+
 2017-03-21  Simon Fraser  <simon.fra...@apple.com>
 
         Remove logging left in by mistake.

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.h (214226 => 214227)


--- trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.h	2017-03-21 18:18:35 UTC (rev 214226)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.h	2017-03-21 19:45:38 UTC (rev 214227)
@@ -30,7 +30,6 @@
 
 #include "AudioSourceProvider.h"
 #include <atomic>
-#include <wtf/Lock.h>
 #include <wtf/MediaTime.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
@@ -90,7 +89,6 @@
     std::unique_ptr<AudioStreamBasicDescription> m_outputDescription;
     std::unique_ptr<CARingBuffer> m_ringBuffer;
 
-    Lock m_mutex;
     MediaTime m_startTimeAtLastProcess;
     MediaTime m_endTimeAtLastProcess;
     std::atomic<uint64_t> m_writeAheadCount { 0 };
@@ -99,6 +97,9 @@
     std::atomic<uint64_t> m_seekTo { NoSeek };
     bool m_paused { true };
     AudioSourceProviderClient* m_client { nullptr };
+
+    struct TapStorage;
+    TapStorage* m_tapStorage { nullptr };
 };
     
 }

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm (214226 => 214227)


--- trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm	2017-03-21 18:18:35 UTC (rev 214226)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm	2017-03-21 19:45:38 UTC (rev 214227)
@@ -40,6 +40,7 @@
 #import <AVFoundation/AVPlayerItem.h>
 #import <mutex>
 #import <objc/runtime.h>
+#import <wtf/Lock.h>
 #import <wtf/MainThread.h>
 
 #if !LOG_DISABLED
@@ -70,6 +71,12 @@
 
 static const double kRingBufferDuration = 1;
 
+struct AudioSourceProviderAVFObjC::TapStorage {
+    TapStorage(AudioSourceProviderAVFObjC* _this) : _this(_this) { }
+    AudioSourceProviderAVFObjC* _this;
+    Lock mutex;
+};
+
 RefPtr<AudioSourceProviderAVFObjC> AudioSourceProviderAVFObjC::create(AVPlayerItem *item)
 {
     if (!canLoadMTAudioProcessingTapCreate())
@@ -85,6 +92,11 @@
 AudioSourceProviderAVFObjC::~AudioSourceProviderAVFObjC()
 {
     setClient(nullptr);
+    if (m_tapStorage) {
+        std::unique_lock<Lock> lock(m_tapStorage->mutex);
+        m_tapStorage->_this = nullptr;
+        m_tapStorage = nullptr;
+    }
 }
 
 void AudioSourceProviderAVFObjC::provideInput(AudioBus* bus, size_t framesToProcess)
@@ -92,7 +104,12 @@
     // Protect access to m_ringBuffer by try_locking the mutex. If we failed
     // to aquire, a re-configure is underway, and m_ringBuffer is unsafe to access.
     // Emit silence.
-    std::unique_lock<Lock> lock(m_mutex, std::try_to_lock);
+    if (!m_tapStorage) {
+        bus->zero();
+        return;
+    }
+
+    std::unique_lock<Lock> lock(m_tapStorage->mutex, std::try_to_lock);
     if (!lock.owns_lock() || !m_ringBuffer) {
         bus->zero();
         return;
@@ -222,35 +239,54 @@
 {
     AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(clientInfo);
     _this->m_tap = tap;
+    _this->m_tapStorage = new TapStorage(_this);
     _this->init(clientInfo, tapStorageOut);
+    *tapStorageOut = _this->m_tapStorage;
 }
 
 void AudioSourceProviderAVFObjC::finalizeCallback(MTAudioProcessingTapRef tap)
 {
     ASSERT(tap);
-    AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(MTAudioProcessingTapGetStorage(tap));
-    _this->finalize();
+    TapStorage* tapStorage = static_cast<TapStorage*>(MTAudioProcessingTapGetStorage(tap));
+
+    std::lock_guard<Lock> lock(tapStorage->mutex);
+
+    if (tapStorage->_this)
+        tapStorage->_this->finalize();
+    delete tapStorage;
 }
 
 void AudioSourceProviderAVFObjC::prepareCallback(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat)
 {
     ASSERT(tap);
-    AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(MTAudioProcessingTapGetStorage(tap));
-    _this->prepare(maxFrames, processingFormat);
+    TapStorage* tapStorage = static_cast<TapStorage*>(MTAudioProcessingTapGetStorage(tap));
+
+    std::lock_guard<Lock> lock(tapStorage->mutex);
+
+    if (tapStorage->_this)
+        tapStorage->_this->prepare(maxFrames, processingFormat);
 }
 
 void AudioSourceProviderAVFObjC::unprepareCallback(MTAudioProcessingTapRef tap)
 {
     ASSERT(tap);
-    AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(MTAudioProcessingTapGetStorage(tap));
-    _this->unprepare();
+    TapStorage* tapStorage = static_cast<TapStorage*>(MTAudioProcessingTapGetStorage(tap));
+
+    std::lock_guard<Lock> lock(tapStorage->mutex);
+
+    if (tapStorage->_this)
+        tapStorage->_this->unprepare();
 }
 
 void AudioSourceProviderAVFObjC::processCallback(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
 {
     ASSERT(tap);
-    AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(MTAudioProcessingTapGetStorage(tap));
-    _this->process(numberFrames, flags, bufferListInOut, numberFramesOut, flagsOut);
+    TapStorage* tapStorage = static_cast<TapStorage*>(MTAudioProcessingTapGetStorage(tap));
+
+    std::lock_guard<Lock> lock(tapStorage->mutex);
+
+    if (tapStorage->_this)
+        tapStorage->_this->process(numberFrames, flags, bufferListInOut, numberFramesOut, flagsOut);
 }
 
 void AudioSourceProviderAVFObjC::init(void* clientInfo, void** tapStorageOut)
@@ -262,6 +298,10 @@
 
 void AudioSourceProviderAVFObjC::finalize()
 {
+    if (m_tapStorage) {
+        m_tapStorage->_this = nullptr;
+        m_tapStorage = nullptr;
+    }
 }
 
 void AudioSourceProviderAVFObjC::prepare(CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat)
@@ -268,8 +308,6 @@
 {
     ASSERT(maxFrames >= 0);
 
-    std::lock_guard<Lock> lock(m_mutex);
-
     m_tapDescription = std::make_unique<AudioStreamBasicDescription>(*processingFormat);
     int numberOfChannels = processingFormat->mChannelsPerFrame;
     double sampleRate = processingFormat->mSampleRate;
@@ -312,8 +350,6 @@
 
 void AudioSourceProviderAVFObjC::unprepare()
 {
-    std::lock_guard<Lock> lock(m_mutex);
-
     m_tapDescription = nullptr;
     m_outputDescription = nullptr;
     m_ringBuffer = nullptr;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to