Bug 1276156: Stop encoder ProcessThreads before deleting the channel r=pkerr

To avoid deadlocks between DeleteChannel() and Process() code

MozReview-Commit-ID: G650SWDH8s0
This commit is contained in:
Randell Jesup 2016-05-31 23:39:34 -04:00
parent a649636701
commit 21cc78c1a6
4 changed files with 37 additions and 4 deletions

View File

@ -281,6 +281,18 @@ bool ChannelGroup::CreateChannel(int channel_id,
return true;
}
void ChannelGroup::Stop(int channel_id) {
ViEEncoder* vie_encoder = GetEncoder(channel_id);
DCHECK(vie_encoder != NULL);
// If we're owning the encoder, remove the feedback and stop all encoding
// threads and processing. This must be done before deleting the channel.
if (vie_encoder->channel_id() == channel_id) {
encoder_state_feedback_->RemoveEncoder(vie_encoder);
vie_encoder->StopThreadsAndRemoveSharedMembers();
}
}
void ChannelGroup::DeleteChannel(int channel_id) {
ViEChannel* vie_channel = PopChannel(channel_id);

View File

@ -52,6 +52,7 @@ class ChannelGroup : public BitrateObserver {
int base_channel_id,
int number_of_cores,
bool disable_default_encoder);
void Stop(int channel_id);
void DeleteChannel(int channel_id);
void AddChannel(int channel_id);
void RemoveChannel(int channel_id);

View File

@ -147,6 +147,23 @@ int ViEChannelManager::CreateChannel(int* channel_id,
int ViEChannelManager::DeleteChannel(int channel_id) {
ChannelGroup* group = NULL;
{
// Read lock to make sure no one tries to delete it on us
ViEChannelManagerScoped(*this);
// Protect the maps.
CriticalSectionScoped cs(channel_id_critsect_);
group = FindGroup(channel_id);
if (group == NULL)
return -1;
group->Stop(channel_id);
}
// Now release the read lock, and get a write lock since we know the
// threads are stopped. Otherwise we can deadlock if we hold a write
// lock and the thread is processing and needs a read lock, and we try to
// stop the thread (ProcessThread::DeRegisterModule(). See Mozilla
// bug 1276156.
{
// Write lock to make sure no one is using the channel.
ViEManagerWriteScoped wl(this);

View File

@ -220,10 +220,13 @@ void ViEEncoder::StartThreadsAndSetSharedMembers(
}
void ViEEncoder::StopThreadsAndRemoveSharedMembers() {
vcm_.RegisterProtectionCallback(NULL);
vcm_protection_callback_ = NULL;
module_process_thread_.DeRegisterModule(&vcm_);
module_process_thread_.DeRegisterModule(&vpm_);
// Avoid trying to stop the threads/etc twice
if (vcm_protection_callback_) {
vcm_.RegisterProtectionCallback(NULL);
vcm_protection_callback_ = NULL;
module_process_thread_.DeRegisterModule(&vcm_);
module_process_thread_.DeRegisterModule(&vpm_);
}
}
void ViEEncoder::SetLoadManager(CPULoadStateCallbackInvoker* load_manager) {