2121#include " rmw/allocators.h"
2222#include " rmw/error_handling.h"
2323#include " rmw/rmw.h"
24+ #include " rmw/validate_full_topic_name.h"
25+
26+ #include " rcpputils/scope_exit.hpp"
2427
2528#include " rmw_fastrtps_shared_cpp/custom_participant_info.hpp"
2629#include " rmw_fastrtps_shared_cpp/custom_subscriber_info.hpp"
@@ -55,27 +58,30 @@ create_subscription(
5558 bool keyed,
5659 bool create_subscription_listener)
5760{
58- if (!topic_name || strlen (topic_name) == 0 ) {
59- RMW_SET_ERROR_MSG (" subscription topic is null or empty string" );
60- return nullptr ;
61- }
62- if (!qos_policies) {
63- RMW_SET_ERROR_MSG (" qos_policies is null" );
64- return nullptr ;
65- }
66- if (!subscription_options) {
67- RMW_SET_ERROR_MSG (" subscription_options is null" );
61+ RMW_CHECK_ARGUMENT_FOR_NULL (participant_info, nullptr );
62+ RMW_CHECK_ARGUMENT_FOR_NULL (type_supports, nullptr );
63+ RMW_CHECK_ARGUMENT_FOR_NULL (topic_name, nullptr );
64+ if (0 == strlen (topic_name)) {
65+ RMW_SET_ERROR_MSG (" topic_name argument is an empty string" );
6866 return nullptr ;
6967 }
70- if (!participant_info) {
71- RMW_SET_ERROR_MSG (" participant_info is null" );
72- return nullptr ;
68+ RMW_CHECK_ARGUMENT_FOR_NULL (qos_policies, nullptr );
69+ if (!qos_policies->avoid_ros_namespace_conventions ) {
70+ int validation_result = RMW_TOPIC_VALID;
71+ rmw_ret_t ret = rmw_validate_full_topic_name (topic_name, &validation_result, nullptr );
72+ if (RMW_RET_OK != ret) {
73+ return nullptr ;
74+ }
75+ if (RMW_TOPIC_VALID != validation_result) {
76+ const char * reason = rmw_full_topic_name_validation_result_string (validation_result);
77+ RMW_SET_ERROR_MSG_WITH_FORMAT_STRING (" invalid topic_name argument: %s" , reason);
78+ return nullptr ;
79+ }
7380 }
81+ RMW_CHECK_ARGUMENT_FOR_NULL (subscription_options, nullptr );
7482 Participant * participant = participant_info->participant ;
75- if (!participant) {
76- RMW_SET_ERROR_MSG (" participant handle is null" );
77- return nullptr ;
78- }
83+ RMW_CHECK_FOR_NULL_WITH_MSG (participant, " participant handle is null" , return nullptr );
84+
7985 const rosidl_message_type_support_t * type_support = get_message_typesupport_handle (
8086 type_supports, RMW_FASTRTPS_CPP_TYPESUPPORT_C);
8187 if (!type_support) {
@@ -89,17 +95,31 @@ create_subscription(
8995 if (!is_valid_qos (*qos_policies)) {
9096 return nullptr ;
9197 }
92- CustomSubscriberInfo * info = nullptr ;
93- rmw_subscription_t * rmw_subscription = nullptr ;
94- eprosima::fastrtps::SubscriberAttributes subscriberParam;
9598
9699 // Load default XML profile.
100+ eprosima::fastrtps::SubscriberAttributes subscriberParam;
97101 Domain::getDefaultSubscriberAttributes (subscriberParam);
98- info = new (std::nothrow) CustomSubscriberInfo ();
102+
103+ CustomSubscriberInfo * info = new (std::nothrow) CustomSubscriberInfo ();
99104 if (!info) {
100105 RMW_SET_ERROR_MSG (" failed to allocate CustomSubscriberInfo" );
101106 return nullptr ;
102107 }
108+ auto cleanup_info = rcpputils::make_scope_exit (
109+ [info, participant]() {
110+ if (info->type_support_ ) {
111+ _unregister_type (participant, info->type_support_ );
112+ }
113+ if (info->subscriber_ ) {
114+ if (!Domain::removeSubscriber (info->subscriber_ )) {
115+ RMW_SAFE_FWRITE_TO_STDERR (
116+ " Failed to remove subscriber after '"
117+ RCUTILS_STRINGIFY (__function__) " ' failed.\n " );
118+ }
119+ }
120+ delete info->listener_ ;
121+ delete info;
122+ });
103123 info->typesupport_identifier_ = type_support->typesupport_identifier ;
104124 info->type_support_impl_ = type_support->data ;
105125
@@ -113,7 +133,7 @@ create_subscription(
113133 info->type_support_ = new (std::nothrow) MessageTypeSupport_cpp (callbacks);
114134 if (!info->type_support_ ) {
115135 RMW_SET_ERROR_MSG (" failed to allocate MessageTypeSupport_cpp" );
116- goto fail ;
136+ return nullptr ;
117137 }
118138 _register_type (participant, info->type_support_ );
119139 }
@@ -128,47 +148,49 @@ create_subscription(
128148 subscriberParam.topic .topicName = _create_topic_name (qos_policies, ros_topic_prefix, topic_name);
129149
130150 if (!get_datareader_qos (*qos_policies, subscriberParam)) {
131- RMW_SET_ERROR_MSG (" failed to get datareader qos" );
132- goto fail;
151+ return nullptr ;
133152 }
134- info-> listener_ = nullptr ;
153+
135154 if (create_subscription_listener) {
136155 info->listener_ = new (std::nothrow) SubListener (info);
137156 if (!info->listener_ ) {
138157 RMW_SET_ERROR_MSG (" create_subscriber() could not create subscriber listener" );
139- goto fail ;
158+ return nullptr ;
140159 }
141160 }
161+
142162 info->subscriber_ = Domain::createSubscriber (participant, subscriberParam, info->listener_ );
143163 if (!info->subscriber_ ) {
144164 RMW_SET_ERROR_MSG (" create_subscriber() could not create subscriber" );
145- goto fail ;
165+ return nullptr ;
146166 }
147167 info->subscription_gid_ = rmw_fastrtps_shared_cpp::create_rmw_gid (
148168 eprosima_fastrtps_identifier, info->subscriber_ ->getGuid ());
149- rmw_subscription = rmw_subscription_allocate ();
169+
170+ rmw_subscription_t * rmw_subscription = rmw_subscription_allocate ();
150171 if (!rmw_subscription) {
151172 RMW_SET_ERROR_MSG (" failed to allocate subscription" );
152- goto fail ;
173+ return nullptr ;
153174 }
175+ auto cleanup_subscription = rcpputils::make_scope_exit (
176+ [rmw_subscription]() {
177+ rmw_free (const_cast <char *>(rmw_subscription->topic_name ));
178+ rmw_subscription_free (rmw_subscription);
179+ });
180+
154181 rmw_subscription->implementation_identifier = eprosima_fastrtps_identifier;
155182 rmw_subscription->data = info;
183+
156184 rmw_subscription->topic_name = rcutils_strdup (topic_name, rcutils_get_default_allocator ());
157185 if (!rmw_subscription->topic_name ) {
158186 RMW_SET_ERROR_MSG (" failed to allocate memory for subscription topic name" );
159- goto fail ;
187+ return nullptr ;
160188 }
161-
162189 rmw_subscription->options = *subscription_options;
163- return rmw_subscription;
190+ rmw_subscription-> can_loan_messages = false ;
164191
165- fail:
166- if (info != nullptr ) {
167- delete info->type_support_ ;
168- delete info->listener_ ;
169- delete info;
170- }
171- rmw_subscription_free (rmw_subscription);
172- return nullptr ;
192+ cleanup_subscription.cancel ();
193+ cleanup_info.cancel ();
194+ return rmw_subscription;
173195}
174196} // namespace rmw_fastrtps_cpp
0 commit comments