FIX: fixes deadlock bug of class function to disable scheduling

When calling _diableScheduling of the participant to enable the
own participant for scheduling by the manager the process runned in a
deadlock.

Summary:
1. manager locks mutex mutexSchedulingParticipants_
2. calls schedule class function of participants in the
   schedulingParticipants_ list
3. there the _disableScheduling function is called by the participant
4. which calls the unschedule function of the manager
5. manager tries to lock mutexSchedulingParticipants_ which is already
   locked

Solution:
- this commit adds the following elements to the Manager class:
	1. disableScheduleQueue_
	2. mutexDisableScheduleQueue_
	3. processDisableScheduling_() ( like processConnections() )
- this commit changes the following functions of Manager class:
	1. unschedule( ... ) -> now adds given participant to
	   disableScheduleQueue
	2. scheduleProcess_() -> now also calls the class function
	   processDisableSchedulung_() after processConections_()
This commit is contained in:
Christina Sander 2022-08-30 15:12:51 +02:00
parent 5c2fc37748
commit d268273e3c
Signed by: csander
GPG Key ID: 8A1F9FA7B3420089
2 changed files with 40 additions and 9 deletions

View File

@ -84,6 +84,12 @@
/// mutex to protect connectionQueue_
std::mutex mutexConnectionQueue_;
/// queue for disable scheduling request so the participants are not scheduled by the manager any longer
std::queue<std::shared_ptr<EventManager::Participant>> disableScheduleQueue_;
/// mutex to protect disableScheduleQueue_
std::mutex mutexDisableScheduleQueue_;
/*
* all private methods
*/
@ -113,6 +119,14 @@
*/
void processConnections_();
/**
* @brief disables the scheduling of the requested participants
*
* Removes the participants from the schedulingParticipants_ list that
* should not be scheduled anymore.
*/
void processDisableScheduling_();
/**
* @brief start the main thread
*/

View File

@ -200,6 +200,7 @@
mutexSchedulingParticipants_.unlock();
processConnections_();
processDisableScheduling_();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
@ -331,18 +332,14 @@
}
}
void EventManager::Manager::unschedule(std::shared_ptr<EventManager::Participant> participant )
{
std::lock_guard<std::mutex> guard(mutexSchedulingParticipants_);
auto it = std::find(schedulingParticipants_.begin(), schedulingParticipants_.end(), participant);
if (it != schedulingParticipants_.end())
{
schedulingParticipants_.erase(it);
}
std::lock_guard<std::mutex> guard( mutexDisableScheduleQueue_ );
disableScheduleQueue_.push( participant );
}
void EventManager::Manager::processConnections_()
{
std::lock_guard<std::mutex> guard(mutexParticipants_);
@ -354,11 +351,31 @@
connectionQueue_.pop();
participants_.push_back(participant);
participant->init();
}
}
void EventManager::Manager::processDisableScheduling_()
{
std::lock_guard<std::mutex> guard( mutexDisableScheduleQueue_ );
while( disableScheduleQueue_.empty() != true )
{
std::shared_ptr<EventManager::Participant> participant = disableScheduleQueue_.front();
disableScheduleQueue_.pop();
std::unique_lock<std::mutex> lk(mutexSchedulingParticipants_);
auto it = std::find(schedulingParticipants_.begin(), schedulingParticipants_.end(), participant);
if (it != schedulingParticipants_.end())
{
schedulingParticipants_.erase(it);
}
lk.unlock();
}
}
void EventManager::Manager::connect(std::shared_ptr<EventManager::Participant> participant)
{
std::lock_guard<std::mutex> guard(mutexParticipants_);