From 010464069ff346ccbd79f60241cfce351b0af1ec Mon Sep 17 00:00:00 2001 From: Meixner <andre.meixner@kit.edu> Date: Mon, 12 Aug 2024 12:30:09 +0200 Subject: [PATCH] Improved locking of subskillsMutex during callSubskillAsync to avoid possible deadlock during abortion of skills --- .../RobotAPI/libraries/skills/core/Skill.cpp | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/source/RobotAPI/libraries/skills/core/Skill.cpp b/source/RobotAPI/libraries/skills/core/Skill.cpp index 7075ae86d..ba6fca085 100644 --- a/source/RobotAPI/libraries/skills/core/Skill.cpp +++ b/source/RobotAPI/libraries/skills/core/Skill.cpp @@ -48,10 +48,11 @@ namespace armarx skills::SkillExecutionID Skill::callSubskillAsync(const skills::SkillProxy& prx, const aron::data::DictPtr& params) { - std::unique_lock l(subskillsMutex); - std::string executorHistory = this->executorName + "->" + getSkillId().toString(); auto eid = prx.executeSkillAsync(executorHistory, params); + + std::unique_lock l(subskillsMutex); + throwIfSkillShouldTerminate([&](){prx.abortSkillAsync(eid);}); // also notify newly added skill as it was not added to subskills list yet this->subskills.push_back(eid); return eid; } @@ -338,6 +339,11 @@ namespace armarx void Skill::notifySkillToStop() { + if (stopped) + { + // skill already got stopped. Ignore + return; + } std::scoped_lock l(subskillsMutex); stopped = true; _onStopRequested(); @@ -347,6 +353,12 @@ namespace armarx void Skill::notifyTimeoutReached() { + if (stopped || timeoutReached) + { + // skill already got timeoutReached. Ignore + return; + } + std::scoped_lock l(subskillsMutex); timeoutReached = true; _onTimeoutReached(); @@ -363,10 +375,13 @@ namespace armarx void Skill::_onTimeoutReached() { + // WE ASSUME THAT THE LOCK IS ALREADY TAKEN + if (!manager) { return; } + for (const auto& execId : subskills) { manager->abortSkillAsync(execId.toManagerIce()); @@ -376,10 +391,13 @@ namespace armarx void Skill::_onStopRequested() { + // WE ASSUME THAT THE LOCK IS ALREADY TAKEN + if (!manager) { return; } + for (const auto& execId : subskills) { manager->abortSkillAsync(execId.toManagerIce()); -- GitLab