Skip to content

Commit 255b746

Browse files
Janosch MachowinskiJanosch Machowinski
authored andcommitted
!fix(Client): Do not hold goal_handle ptr if result cb is set.
The capture of the lambda held an copy of the shared_ptr to the goal handle. This lead to the behavior that the goal callbacks would be called, even though the user dropped the handle. Note, this will break the current tutorial, as it restores the documented behavior that a goal will be invalidated as soon as one drops the handle. Signed-off-by: Janosch Machowinski <[email protected]>
1 parent b50f9ab commit 255b746

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

rclcpp_action/include/rclcpp_action/client.hpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -708,23 +708,40 @@ class Client : public ClientBase
708708
}
709709
using GoalResultRequest = typename ActionT::Impl::GetResultService::Request;
710710
auto goal_result_request = std::make_shared<GoalResultRequest>();
711+
const GoalUUID goal_id = goal_handle->get_goal_id();
711712
goal_result_request->goal_id.uuid = goal_handle->get_goal_id();
712713
try {
713714
this->send_result_request(
714715
std::static_pointer_cast<void>(goal_result_request),
715-
[goal_handle, this](std::shared_ptr<void> response) mutable
716+
[goal_id, this](std::shared_ptr<void> response) mutable
716717
{
718+
std::lock_guard<std::mutex> lock(goal_handles_mutex_);
719+
if (goal_handles_.count(goal_id) == 0) {
720+
RCLCPP_DEBUG(
721+
this->get_logger(),
722+
"Received result for unknown goal. Ignoring...");
723+
return;
724+
}
725+
typename GoalHandle::SharedPtr goal_handle_ = goal_handles_[goal_id].lock();
726+
// Forget about the goal if there are no more user references
727+
if (!goal_handle_) {
728+
RCLCPP_DEBUG(
729+
this->get_logger(),
730+
"Dropping weak reference to goal handle during result callback");
731+
goal_handles_.erase(goal_id);
732+
return;
733+
}
734+
717735
// Wrap the response in a struct with the fields a user cares about
718736
WrappedResult wrapped_result;
719737
using GoalResultResponse = typename ActionT::Impl::GetResultService::Response;
720738
auto result_response = std::static_pointer_cast<GoalResultResponse>(response);
721739
wrapped_result.result = std::make_shared<typename ActionT::Result>();
722740
*wrapped_result.result = result_response->result;
723-
wrapped_result.goal_id = goal_handle->get_goal_id();
741+
wrapped_result.goal_id = goal_id;
724742
wrapped_result.code = static_cast<ResultCode>(result_response->status);
725-
goal_handle->set_result(wrapped_result);
726-
std::lock_guard<std::mutex> lock(goal_handles_mutex_);
727-
goal_handles_.erase(goal_handle->get_goal_id());
743+
goal_handle_->set_result(wrapped_result);
744+
goal_handles_.erase(goal_id);
728745
});
729746
} catch (rclcpp::exceptions::RCLError & ex) {
730747
// This will cause an exception when the user tries to access the result

0 commit comments

Comments
 (0)