Skip to content

Commit

Permalink
Declare rclcpp callbacks before the rcl entities (ros2#2024)
Browse files Browse the repository at this point in the history
This is to ensure callbacks are destroyed last
on entities destruction, avoiding the gap in time
in which rmw entities hold a reference to a
destroyed function.

Signed-off-by: Mauro Passerino <mpasserino@irobot.com>
  • Loading branch information
Mauro Passerino authored and Alberto Soragna committed May 3, 2023
1 parent 51aff6c commit 8c4fb98
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
10 changes: 7 additions & 3 deletions rclcpp/include/rclcpp/client.hpp
Expand Up @@ -388,6 +388,13 @@ class ClientBase
std::shared_ptr<rclcpp::Context> context_;
rclcpp::Logger node_logger_;

std::recursive_mutex callback_mutex_;
// It is important to declare on_new_response_callback_ before
// client_handle_, so on destruction the client is
// destroyed first. Otherwise, the rmw client callback
// would point briefly to a destroyed function.
std::function<void(size_t)> on_new_response_callback_{nullptr};
// Declare client_handle_ after callback
std::shared_ptr<rcl_client_t> client_handle_;

std::atomic<bool> in_use_by_wait_set_{false};
Expand All @@ -396,9 +403,6 @@ class ClientBase
bool use_intra_process_{false};
IntraProcessManagerWeakPtr weak_ipm_;
uint64_t intra_process_client_id_;

std::recursive_mutex callback_mutex_;
std::function<void(size_t)> on_new_response_callback_{nullptr};
};

template<typename ServiceT>
Expand Down
1 change: 0 additions & 1 deletion rclcpp/include/rclcpp/service.hpp
Expand Up @@ -302,7 +302,6 @@ class ServiceBase
// would point briefly to a destroyed function.
std::function<void(size_t)> on_new_request_callback_{nullptr};
// Declare service_handle_ after callback

std::shared_ptr<rcl_service_t> service_handle_;
bool owns_rcl_handle_ = true;

Expand Down
11 changes: 8 additions & 3 deletions rclcpp/include/rclcpp/subscription_base.hpp
Expand Up @@ -558,6 +558,14 @@ class SubscriptionBase : public std::enable_shared_from_this<SubscriptionBase>
rclcpp::node_interfaces::NodeBaseInterface * const node_base_;

std::shared_ptr<rcl_node_t> node_handle_;

std::recursive_mutex callback_mutex_;
// It is important to declare on_new_message_callback_ before
// subscription_handle_, so on destruction the subscription is
// destroyed first. Otherwise, the rmw subscription callback
// would point briefly to a destroyed function.
std::function<void(size_t)> on_new_message_callback_{nullptr};
// Declare subscription_handle_ after callback
std::shared_ptr<rcl_subscription_t> subscription_handle_;
std::shared_ptr<rcl_subscription_t> intra_process_subscription_handle_;
rclcpp::Logger node_logger_;
Expand All @@ -580,9 +588,6 @@ class SubscriptionBase : public std::enable_shared_from_this<SubscriptionBase>
std::atomic<bool> intra_process_subscription_waitable_in_use_by_wait_set_{false};
std::unordered_map<rclcpp::QOSEventHandlerBase *,
std::atomic<bool>> qos_events_in_use_by_wait_set_;

std::recursive_mutex callback_mutex_;
std::function<void(size_t)> on_new_message_callback_{nullptr};
};

} // namespace rclcpp
Expand Down

0 comments on commit 8c4fb98

Please sign in to comment.