From d268273e3ca37c64b657a3ffd2190923b904b989 Mon Sep 17 00:00:00 2001 From: Christina Sander Date: Tue, 30 Aug 2022 15:12:51 +0200 Subject: [PATCH] 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_() --- include/EventManager/Manager.hpp | 14 +++++++++++++ src/EventManager/Manager.cpp | 35 ++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/EventManager/Manager.hpp b/include/EventManager/Manager.hpp index 7ba77b6..e186503 100644 --- a/include/EventManager/Manager.hpp +++ b/include/EventManager/Manager.hpp @@ -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> 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 */ diff --git a/src/EventManager/Manager.cpp b/src/EventManager/Manager.cpp index 37bdb91..1499951 100644 --- a/src/EventManager/Manager.cpp +++ b/src/EventManager/Manager.cpp @@ -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 participant ) { - std::lock_guard guard(mutexSchedulingParticipants_); - - auto it = std::find(schedulingParticipants_.begin(), schedulingParticipants_.end(), participant); - - if (it != schedulingParticipants_.end()) - { - schedulingParticipants_.erase(it); - } + std::lock_guard guard( mutexDisableScheduleQueue_ ); + disableScheduleQueue_.push( participant ); } + void EventManager::Manager::processConnections_() { std::lock_guard guard(mutexParticipants_); @@ -354,11 +351,31 @@ connectionQueue_.pop(); participants_.push_back(participant); - participant->init(); } } + + void EventManager::Manager::processDisableScheduling_() + { + std::lock_guard guard( mutexDisableScheduleQueue_ ); + while( disableScheduleQueue_.empty() != true ) + { + std::shared_ptr participant = disableScheduleQueue_.front(); + disableScheduleQueue_.pop(); + + std::unique_lock 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 participant) { std::lock_guard guard(mutexParticipants_);