@@ -500,9 +500,13 @@ ServerBase::execute_result_request_received(std::shared_ptr<void> & data)
500500 result_response = create_result_response (action_msgs::msg::GoalStatus::STATUS_UNKNOWN);
501501 } else {
502502 // Goal exists, check if a result is already available
503+ std::lock_guard<std::recursive_mutex> lock (pimpl_->unordered_map_mutex_ );
503504 auto iter = pimpl_->goal_results_ .find (uuid);
504505 if (iter != pimpl_->goal_results_ .end ()) {
505506 result_response = iter->second ;
507+ } else {
508+ // Store the request so it can be responded to later
509+ pimpl_->result_requests_ [uuid].push_back (request_header);
506510 }
507511 }
508512
@@ -514,10 +518,6 @@ ServerBase::execute_result_request_received(std::shared_ptr<void> & data)
514518 if (RCL_RET_OK != rcl_ret) {
515519 rclcpp::exceptions::throw_from_rcl_error (rcl_ret);
516520 }
517- } else {
518- // Store the request so it can be responded to later
519- std::lock_guard<std::recursive_mutex> lock (pimpl_->unordered_map_mutex_ );
520- pimpl_->result_requests_ [uuid].push_back (request_header);
521521 }
522522 data.reset ();
523523}
@@ -627,19 +627,30 @@ ServerBase::publish_result(const GoalUUID & uuid, std::shared_ptr<void> result_m
627627 }
628628
629629 {
630- std::lock_guard<std::recursive_mutex> lock (pimpl_->unordered_map_mutex_ );
630+ /* *
631+ * NOTE: There is a potential deadlock issue if both unordered_map_mutex_ and
632+ * action_server_reentrant_mutex_ locked in other block scopes. Unless using
633+ * std::scoped_lock, locking order must be consistent with the current.
634+ *
635+ * Current locking order:
636+ *
637+ * 1. unordered_map_mutex_
638+ * 2. action_server_reentrant_mutex_
639+ *
640+ */
641+ std::lock_guard<std::recursive_mutex> unordered_map_lock (pimpl_->unordered_map_mutex_ );
631642 pimpl_->goal_results_ [uuid] = result_msg;
632- }
633643
634- // if there are clients who already asked for the result, send it to them
635- auto iter = pimpl_->result_requests_ .find (uuid);
636- if (iter != pimpl_->result_requests_ .end ()) {
637- for (auto & request_header : iter->second ) {
644+ // if there are clients who already asked for the result, send it to them
645+ auto iter = pimpl_->result_requests_ .find (uuid);
646+ if (iter != pimpl_->result_requests_ .end ()) {
638647 std::lock_guard<std::recursive_mutex> lock (pimpl_->action_server_reentrant_mutex_ );
639- rcl_ret_t ret = rcl_action_send_result_response (
640- pimpl_->action_server_ .get (), &request_header, result_msg.get ());
641- if (RCL_RET_OK != ret) {
642- rclcpp::exceptions::throw_from_rcl_error (ret);
648+ for (auto & request_header : iter->second ) {
649+ rcl_ret_t ret = rcl_action_send_result_response (
650+ pimpl_->action_server_ .get (), &request_header, result_msg.get ());
651+ if (RCL_RET_OK != ret) {
652+ rclcpp::exceptions::throw_from_rcl_error (ret);
653+ }
643654 }
644655 }
645656 }
0 commit comments