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

Changeset 278289 in webkit


Ignore:
Timestamp:
May 31, 2021, 5:09:42 PM (5 years ago)
Author:
Chris Dumez
Message:

Fix thread safety issues in ConvolverNode
https://bugs.webkit.org/show_bug.cgi?id=226449

Reviewed by Darin Adler.

Adopt thread safety annotations in ConvolverNode and fix bugs found by clang.
In particular, the following issues were found and fixed:

  • tailTime() / latencyTime() were accessing m_reverb on the audio thread without locking even though m_reverb gets modified on the main thread.
  • checkNumberOfChannelsForInput() was accessing m_buffer on the audio thread without locking even though m_buffer gets modified on the main thread.
  • Modules/webaudio/ConvolverNode.cpp:

(WebCore::ConvolverNode::create):
(WebCore::ConvolverNode::setBufferForBindings):
(WebCore::ConvolverNode::setNormalizeForBindings):
(WebCore::ConvolverNode::tailTime const):
(WebCore::ConvolverNode::latencyTime const):
(WebCore::ConvolverNode::checkNumberOfChannelsForInput):

  • Modules/webaudio/ConvolverNode.h:
  • Modules/webaudio/ConvolverNode.idl:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r278288 r278289  
     12021-05-31  Chris Dumez  <cdumez@apple.com>
     2
     3        Fix thread safety issues in ConvolverNode
     4        https://bugs.webkit.org/show_bug.cgi?id=226449
     5
     6        Reviewed by Darin Adler.
     7
     8        Adopt thread safety annotations in ConvolverNode and fix bugs found by clang.
     9        In particular, the following issues were found and fixed:
     10        - tailTime() / latencyTime() were accessing m_reverb on the audio thread without
     11          locking even though m_reverb gets modified on the main thread.
     12        - checkNumberOfChannelsForInput() was accessing m_buffer on the audio thread
     13          without locking even though m_buffer gets modified on the main thread.
     14
     15        * Modules/webaudio/ConvolverNode.cpp:
     16        (WebCore::ConvolverNode::create):
     17        (WebCore::ConvolverNode::setBufferForBindings):
     18        (WebCore::ConvolverNode::setNormalizeForBindings):
     19        (WebCore::ConvolverNode::tailTime const):
     20        (WebCore::ConvolverNode::latencyTime const):
     21        (WebCore::ConvolverNode::checkNumberOfChannelsForInput):
     22        * Modules/webaudio/ConvolverNode.h:
     23        * Modules/webaudio/ConvolverNode.idl:
     24
    1252021-05-31  Chris Dumez  <cdumez@apple.com>
    226
  • trunk/Source/WebCore/Modules/webaudio/ConvolverNode.cpp

    r277932 r278289  
    6464        return result.releaseException();
    6565
    66     node->setNormalize(!options.disableNormalization);
    67 
    68     result = node->setBuffer(WTFMove(options.buffer));
     66    node->setNormalizeForBindings(!options.disableNormalization);
     67
     68    result = node->setBufferForBindings(WTFMove(options.buffer));
    6969    if (result.hasException())
    7070        return result.releaseException();
     
    111111}
    112112
    113 ExceptionOr<void> ConvolverNode::setBuffer(RefPtr<AudioBuffer>&& buffer)
     113ExceptionOr<void> ConvolverNode::setBufferForBindings(RefPtr<AudioBuffer>&& buffer)
    114114{
    115115    ASSERT(isMainThread());
     
    161161}
    162162
    163 AudioBuffer* ConvolverNode::buffer()
     163AudioBuffer* ConvolverNode::bufferForBindings() WTF_IGNORES_THREAD_SAFETY_ANALYSIS
    164164{
    165165    ASSERT(isMainThread());
     
    167167}
    168168
     169void ConvolverNode::setNormalizeForBindings(bool normalize)
     170{
     171    ASSERT(isMainThread());
     172    m_normalize = normalize;
     173}
     174
    169175double ConvolverNode::tailTime() const
    170176{
     177    ASSERT(context().isAudioThread());
     178    if (!m_processLock.tryLock())
     179        return std::numeric_limits<double>::infinity();
     180    Locker locker { AdoptLock, m_processLock };
    171181    return m_reverb ? m_reverb->impulseResponseLength() / static_cast<double>(sampleRate()) : 0;
    172182}
     
    174184double ConvolverNode::latencyTime() const
    175185{
     186    ASSERT(context().isAudioThread());
     187    if (!m_processLock.tryLock())
     188        return std::numeric_limits<double>::infinity();
     189    Locker locker { AdoptLock, m_processLock };
    176190    return m_reverb ? m_reverb->latencyFrames() / static_cast<double>(sampleRate()) : 0;
    177191}
     
    200214{
    201215    ASSERT(context().isAudioThread() && context().isGraphOwner());
    202 
    203     if (m_buffer) {
    204         unsigned numberOfOutputChannels = computeNumberOfOutputChannels(input->numberOfChannels(), m_buffer->numberOfChannels());
     216    std::optional<unsigned> numberOfBufferChannels;
     217    if (m_processLock.tryLock()) {
     218        Locker locker { AdoptLock, m_processLock };
     219        if (m_buffer)
     220            numberOfBufferChannels = m_buffer->numberOfChannels();
     221    }
     222
     223    if (numberOfBufferChannels) {
     224        unsigned numberOfOutputChannels = computeNumberOfOutputChannels(input->numberOfChannels(), *numberOfBufferChannels);
    205225
    206226        if (isInitialized() && numberOfOutputChannels != output(0)->numberOfChannels()) {
  • trunk/Source/WebCore/Modules/webaudio/ConvolverNode.h

    r268001 r278289  
    4242    virtual ~ConvolverNode();
    4343   
    44     ExceptionOr<void> setBuffer(RefPtr<AudioBuffer>&&);
    45     AudioBuffer* buffer();
     44    ExceptionOr<void> setBufferForBindings(RefPtr<AudioBuffer>&&);
     45    AudioBuffer* bufferForBindings(); // Only safe to call on the main thread.
    4646
    47     bool normalize() const { return m_normalize; }
    48     void setNormalize(bool normalize) { m_normalize = normalize; }
     47    bool normalizeForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_normalize; }
     48    void setNormalizeForBindings(bool);
    4949
    5050    ExceptionOr<void> setChannelCount(unsigned) final;
     
    6161    void checkNumberOfChannelsForInput(AudioNodeInput*) final;
    6262
    63     std::unique_ptr<Reverb> m_reverb;
    64     RefPtr<AudioBuffer> m_buffer;
     63    std::unique_ptr<Reverb> m_reverb WTF_GUARDED_BY_LOCK(m_processLock); // Only modified on the main thread but accessed on the audio thread.
     64    RefPtr<AudioBuffer> m_buffer WTF_GUARDED_BY_LOCK(m_processLock); // Only modified on the main thread but accessed on the audio thread.
    6565
    6666    // This synchronizes dynamic changes to the convolution impulse response with process().
     
    6868
    6969    // Normalize the impulse response or not.
    70     bool m_normalize { true };
     70    bool m_normalize { true }; // Only used on the main thread.
    7171};
    7272
  • trunk/Source/WebCore/Modules/webaudio/ConvolverNode.idl

    r276715 r278289  
    3232    [EnabledBySetting=WebAudio] constructor (BaseAudioContext context, optional ConvolverOptions options);
    3333
    34     attribute AudioBuffer? buffer;
    35     attribute boolean normalize;
     34    [ImplementedAs=bufferForBindings] attribute AudioBuffer? buffer;
     35    [ImplementedAs=normalizeForBindings] attribute boolean normalize;
    3636};
Note: See TracChangeset for help on using the changeset viewer.