2121#include < sstream>
2222#include < string>
2323
24+ #include " rcutils/logging_macros.h"
25+
2426#include " rcl/error_handling.h"
2527#include " rcl/service.h"
2628
3032#include " rclcpp/type_support_decl.hpp"
3133#include " rclcpp/expand_topic_or_service_name.hpp"
3234#include " rclcpp/visibility_control.hpp"
35+ #include " rclcpp/logging.hpp"
3336#include " rmw/error_handling.h"
3437#include " rmw/rmw.h"
3538
@@ -58,11 +61,11 @@ class ServiceBase
5861 get_service_name ();
5962
6063 RCLCPP_PUBLIC
61- rcl_service_t *
64+ std::shared_ptr< rcl_service_t >
6265 get_service_handle ();
6366
6467 RCLCPP_PUBLIC
65- const rcl_service_t *
68+ std::shared_ptr< const rcl_service_t >
6669 get_service_handle () const ;
6770
6871 virtual std::shared_ptr<void > create_request () = 0;
@@ -84,7 +87,7 @@ class ServiceBase
8487
8588 std::shared_ptr<rcl_node_t > node_handle_;
8689
87- rcl_service_t * service_handle_ = nullptr ;
90+ std::shared_ptr< rcl_service_t > service_handle_;
8891 std::string service_name_;
8992 bool owns_rcl_handle_ = true ;
9093};
@@ -116,11 +119,22 @@ class Service : public ServiceBase
116119 auto service_type_support_handle = get_service_type_support_handle<ServiceT>();
117120
118121 // rcl does the static memory allocation here
119- service_handle_ = new rcl_service_t ;
120- *service_handle_ = rcl_get_zero_initialized_service ();
122+ service_handle_ = std::shared_ptr<rcl_service_t >(
123+ new rcl_service_t , [ = ](rcl_service_t * service)
124+ {
125+ if (rcl_service_fini (service, node_handle_.get ()) != RCL_RET_OK) {
126+ RCLCPP_ERROR (
127+ rclcpp::get_logger (rcl_node_get_name (node_handle.get ())).get_child (" rclcpp" ),
128+ " Error in destruction of rcl service handle: %s" ,
129+ rcl_get_error_string_safe ());
130+ rcl_reset_error ();
131+ }
132+ delete service;
133+ });
134+ *service_handle_.get () = rcl_get_zero_initialized_service ();
121135
122136 rcl_ret_t ret = rcl_service_init (
123- service_handle_,
137+ service_handle_. get () ,
124138 node_handle.get (),
125139 service_type_support_handle,
126140 service_name.c_str (),
@@ -141,6 +155,29 @@ class Service : public ServiceBase
141155 }
142156 }
143157
158+ Service (
159+ std::shared_ptr<rcl_node_t > node_handle,
160+ std::shared_ptr<rcl_service_t > service_handle,
161+ AnyServiceCallback<ServiceT> any_callback)
162+ : ServiceBase(node_handle),
163+ any_callback_ (any_callback)
164+ {
165+ // check if service handle was initialized
166+ if (!rcl_service_is_valid (service_handle.get (), nullptr )) {
167+ // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
168+ throw std::runtime_error (
169+ std::string (" rcl_service_t in constructor argument must be initialized beforehand." ));
170+ // *INDENT-ON*
171+ }
172+
173+ const char * service_name = rcl_service_get_service_name (service_handle.get ());
174+ if (!service_name) {
175+ throw std::runtime_error (" failed to get service name" );
176+ }
177+ service_handle_ = service_handle;
178+ service_name_ = std::string (service_name);
179+ }
180+
144181 Service (
145182 std::shared_ptr<rcl_node_t > node_handle,
146183 rcl_service_t * service_handle,
@@ -149,10 +186,7 @@ class Service : public ServiceBase
149186 any_callback_(any_callback)
150187 {
151188 // check if service handle was initialized
152- // TODO(karsten1987): Take this verification
153- // directly in rcl_*_t
154- // see: https://github.com/ros2/rcl/issues/81
155- if (!service_handle->impl ) {
189+ if (!rcl_service_is_valid (service_handle, nullptr )) {
156190 // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
157191 throw std::runtime_error (
158192 std::string (" rcl_service_t in constructor argument must be initialized beforehand." ));
@@ -163,26 +197,17 @@ class Service : public ServiceBase
163197 if (!service_name) {
164198 throw std::runtime_error (" failed to get service name" );
165199 }
166- service_handle_ = service_handle;
167200 service_name_ = std::string (service_name);
168- owns_rcl_handle_ = false ;
201+
202+ // In this case, rcl owns the service handle memory
203+ service_handle_ = std::shared_ptr<rcl_service_t >(new rcl_service_t );
204+ service_handle_->impl = service_handle->impl ;
169205 }
170206
171207 Service () = delete;
172208
173209 virtual ~Service ()
174210 {
175- // check if you have ownership of the handle
176- if (owns_rcl_handle_) {
177- if (rcl_service_fini (service_handle_, node_handle_.get ()) != RCL_RET_OK) {
178- std::stringstream ss;
179- ss << " Error in destruction of rcl service_handle_ handle: " <<
180- rcl_get_error_string_safe () << ' \n ' ;
181- (std::cerr << ss.str ()).flush ();
182- rcl_reset_error ();
183- }
184- delete service_handle_;
185- }
186211 }
187212
188213 std::shared_ptr<void > create_request ()
@@ -211,7 +236,7 @@ class Service : public ServiceBase
211236 std::shared_ptr<rmw_request_id_t > req_id,
212237 std::shared_ptr<typename ServiceT::Response> response)
213238 {
214- rcl_ret_t status = rcl_send_response (get_service_handle (), req_id.get (), response.get ());
239+ rcl_ret_t status = rcl_send_response (get_service_handle (). get () , req_id.get (), response.get ());
215240
216241 if (status != RCL_RET_OK) {
217242 rclcpp::exceptions::throw_from_rcl_error (status, " failed to send response" );
0 commit comments