Skip to content

Commit bb42c62

Browse files
mauropasseMauro Passerino
andauthored
Fix IPC Actions data race (ros2#147)
* Check if goal was sent through IPC before send responses * Add intra_process_action_server_is_available API to intra-process Client --------- Co-authored-by: Mauro Passerino <[email protected]>
1 parent 4ddaaca commit bb42c62

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

rclcpp/include/rclcpp/experimental/action_client_intra_process_base.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ class ActionClientIntraProcessBase : public rclcpp::Waitable
158158
event_info_multi_map_.erase(goal_id);
159159
}
160160

161+
bool has_goal_id(size_t goal_id) const
162+
{
163+
// Check if the intra-process client has this goal_id
164+
auto it = event_info_multi_map_.find(goal_id);
165+
if (it != event_info_multi_map_.end()) {
166+
return true;
167+
}
168+
169+
return false;
170+
}
171+
161172
private:
162173
std::string action_name_;
163174
QoS qos_profile_;

rclcpp_action/include/rclcpp_action/client.hpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ class ClientBase : public rclcpp::Waitable
9797
);
9898
}
9999

100+
/// Return true if there is an intra-process action server that is ready to take goal requests.
101+
bool
102+
intra_process_action_server_is_available()
103+
{
104+
if (auto ipm = weak_ipm_.lock()) {
105+
return ipm->action_server_is_available(ipc_action_client_id_);
106+
}
107+
return false;
108+
}
109+
100110
// -------------
101111
// Waitables API
102112

@@ -513,13 +523,17 @@ class Client : public ClientBase
513523
// If there's not, we fall back into inter-process communication, since
514524
// the server might be available in another process or was configured to not use IPC.
515525
if (intra_process_server_available) {
516-
ipc_action_client_->store_goal_response_callback(
517-
hashed_guuid, goal_response_callback);
526+
bool goal_sent_by_ipc = ipc_action_client_->has_goal_id(hashed_guuid);
518527

519-
intra_process_send_done = ipm->template intra_process_action_send_goal_request<ActionT>(
520-
ipc_action_client_id_,
521-
std::move(goal_request),
522-
hashed_guuid);
528+
if (goal_sent_by_ipc) {
529+
ipc_action_client_->store_goal_response_callback(
530+
hashed_guuid, goal_response_callback);
531+
532+
intra_process_send_done = ipm->template intra_process_action_send_goal_request<ActionT>(
533+
ipc_action_client_id_,
534+
std::move(goal_request),
535+
hashed_guuid);
536+
}
523537
}
524538
}
525539

@@ -835,12 +849,17 @@ class Client : public ClientBase
835849
// the server might be available in another process or was configured to not use IPC.
836850
if (intra_process_server_available) {
837851
size_t hashed_guuid = std::hash<GoalUUID>()(goal_handle->get_goal_id());
838-
ipc_action_client_->store_result_response_callback(
839-
hashed_guuid, result_response_callback);
840852

841-
intra_process_send_done = ipm->template intra_process_action_send_result_request<ActionT>(
842-
ipc_action_client_id_,
843-
std::move(goal_result_request));
853+
bool goal_sent_by_ipc = ipc_action_client_->has_goal_id(hashed_guuid);
854+
855+
if (goal_sent_by_ipc) {
856+
ipc_action_client_->store_result_response_callback(
857+
hashed_guuid, result_response_callback);
858+
859+
intra_process_send_done = ipm->template intra_process_action_send_result_request<ActionT>(
860+
ipc_action_client_id_,
861+
std::move(goal_result_request));
862+
}
844863
}
845864
}
846865

@@ -891,12 +910,17 @@ class Client : public ClientBase
891910
// the server might be available in another process or was configured to not use IPC.
892911
if (intra_process_server_available) {
893912
size_t hashed_guuid = std::hash<GoalUUID>()(cancel_request->goal_info.goal_id.uuid);
894-
ipc_action_client_->store_cancel_goal_callback(
895-
hashed_guuid, cancel_goal_callback);
896913

897-
intra_process_send_done = ipm->template intra_process_action_send_cancel_request<ActionT>(
914+
bool goal_sent_by_ipc = ipc_action_client_->has_goal_id(hashed_guuid);
915+
916+
if (goal_sent_by_ipc) {
917+
ipc_action_client_->store_cancel_goal_callback(
918+
hashed_guuid, cancel_goal_callback);
919+
920+
intra_process_send_done = ipm->template intra_process_action_send_cancel_request<ActionT>(
898921
ipc_action_client_id_,
899922
std::move(cancel_request));
923+
}
900924
}
901925
}
902926

0 commit comments

Comments
 (0)