diff --git a/webrtc/voice_engine/channel_manager.cc b/webrtc/voice_engine/channel_manager.cc index 6cf935d16..8110bb6a2 100644 --- a/webrtc/voice_engine/channel_manager.cc +++ b/webrtc/voice_engine/channel_manager.cc @@ -78,22 +78,34 @@ void ChannelManager::GetAllChannels(std::vector* channels) { } void ChannelManager::DestroyChannel(int32_t channel_id) { - CriticalSectionScoped crit(lock_.get()); assert(channel_id >= 0); + // Holds a reference to a channel, this is used so that we never delete + // Channels while holding a lock, but rather when the method returns. + ChannelOwner reference(NULL); + { + CriticalSectionScoped crit(lock_.get()); - for (std::vector::iterator it = channels_.begin(); - it != channels_.end(); - ++it) { - if (it->channel()->ChannelId() == channel_id) { - channels_.erase(it); - break; + for (std::vector::iterator it = channels_.begin(); + it != channels_.end(); + ++it) { + if (it->channel()->ChannelId() == channel_id) { + reference = *it; + channels_.erase(it); + break; + } } } } void ChannelManager::DestroyAllChannels() { - CriticalSectionScoped crit(lock_.get()); - channels_.clear(); + // Holds references so that Channels are not destroyed while holding this + // lock, but rather when the method returns. + std::vector references; + { + CriticalSectionScoped crit(lock_.get()); + references = channels_; + channels_.clear(); + } } size_t ChannelManager::NumOfChannels() const {