Chromium Code Reviews| Index: content/renderer/media/webrtc_audio_device_impl.cc |
| diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc |
| index 5b87c186e68d7964acbfe5db0ad513ed59cff2f6..ef925ae54e2e569da9ae7b5971b3cf635ca4a175 100644 |
| --- a/content/renderer/media/webrtc_audio_device_impl.cc |
| +++ b/content/renderer/media/webrtc_audio_device_impl.cc |
| @@ -397,13 +397,30 @@ bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |
| DCHECK(renderer); |
| - base::AutoLock auto_lock(lock_); |
| - if (renderer_.get()) |
| - return false; |
| + // Here we acquire |lock_| in order to protect the internal state. |
| + { |
| + base::AutoLock auto_lock(lock_); |
| + if (renderer_.get()) |
| + return false; |
| + } |
| + // We release |lock_| here because invoking |renderer|->Initialize while |
| + // holding |lock_| would result in locks taken in the sequence |
| + // (|this->lock_|, |renderer->lock_|) while another thread (i.e, the |
| + // AudioOutputDevice thread) might concurrently invoke a renderer method, |
| + // which can itself invoke a method from |this|, resulting in locks taken in |
| + // the sequence (|renderer->lock_|, |this->lock_|) in that thread. |
| + // This order discrepancy can cause a deadlock (see Issue 433993). |
| + // However, we do not need to hold |this->lock_| in order to invoke |
| + // |renderer|->Initialize, since it does not involve any unprotected access to |
| + // the internal state of |this|. |
| if (!renderer->Initialize(this)) |
| return false; |
| + // We acquire |lock_| again and assert our precondition, since we are |
| + // accessing the internal state again. |
| + base::AutoLock auto_lock(lock_); |
| + DCHECK(!renderer_.get()); |
|
tommi (sloooow) - chröme
2015/03/31 08:29:13
Would also be good to have a note here about how i
|
| renderer_ = renderer; |
| return true; |
| } |