Skip to content

Commit 53a0d40

Browse files
Janosch MachowinskiJanosch Machowinski
authored andcommitted
feat: Added check for double usage of entities in rcl_waitset
Adding entities twice to a waitset is not allowed, and will introduce subtle bugs. Therefore the rcl_wait function will not explicitly check for duplicated entries in the waitset. Signed-off-by: Janosch Machowinski <[email protected]>
1 parent 168ea9b commit 53a0d40

12 files changed

+188
-57
lines changed

rcl/src/rcl/client.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,9 @@ extern "C"
3838
#include "rosidl_runtime_c/service_type_support_struct.h"
3939

4040
#include "./common.h"
41+
#include "./client_impl.h"
4142
#include "./service_event_publisher.h"
4243

43-
struct rcl_client_impl_s
44-
{
45-
rcl_client_options_t options;
46-
rmw_qos_profile_t actual_request_publisher_qos;
47-
rmw_qos_profile_t actual_response_subscription_qos;
48-
rmw_client_t * rmw_handle;
49-
atomic_int_least64_t sequence_number;
50-
rcl_service_event_publisher_t * service_event_publisher;
51-
char * remapped_service_name;
52-
rosidl_type_hash_t type_hash;
53-
};
54-
5544
rcl_client_t
5645
rcl_get_zero_initialized_client(void)
5746
{
@@ -178,6 +167,7 @@ rcl_client_init(
178167
// options
179168
client->impl->options = *options;
180169
atomic_init(&client->impl->sequence_number, 0);
170+
client->impl->in_use_by_waitset = false;
181171

182172
const rosidl_type_hash_t * hash = type_support->get_type_hash_func(type_support);
183173
if (hash == NULL) {

rcl/src/rcl/client_impl.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2025 cellumation GmbH
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCL__CLIENT_IMPL_H_
16+
#define RCL__CLIENT_IMPL_H_
17+
18+
#include <stdatomic.h>
19+
20+
#include "rmw/rmw.h"
21+
#include "rcl/client.h"
22+
#include "./service_event_publisher.h"
23+
24+
struct rcl_client_impl_s
25+
{
26+
rcl_client_options_t options;
27+
rmw_qos_profile_t actual_request_publisher_qos;
28+
rmw_qos_profile_t actual_response_subscription_qos;
29+
rmw_client_t * rmw_handle;
30+
atomic_int_least64_t sequence_number;
31+
rcl_service_event_publisher_t * service_event_publisher;
32+
char * remapped_service_name;
33+
rosidl_type_hash_t type_hash;
34+
bool in_use_by_waitset;
35+
};
36+
37+
#endif // RCL__CLIENT_IMPL_H_

rcl/src/rcl/guard_condition.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,8 @@ extern "C"
2525
#include "rmw/rmw.h"
2626

2727
#include "./context_impl.h"
28+
#include "./guard_condition_impl.h"
2829

29-
struct rcl_guard_condition_impl_s
30-
{
31-
rmw_guard_condition_t * rmw_handle;
32-
bool allocated_rmw_guard_condition;
33-
rcl_guard_condition_options_t options;
34-
};
3530

3631
rcl_guard_condition_t
3732
rcl_get_zero_initialized_guard_condition(void)
@@ -74,6 +69,7 @@ __rcl_guard_condition_init_from_rmw_impl(
7469
RCL_SET_ERROR_MSG("allocating memory failed");
7570
return RCL_RET_BAD_ALLOC;
7671
}
72+
guard_condition->impl->in_use_by_waitset = false;
7773
// Create the rmw guard condition.
7874
if (rmw_guard_condition) {
7975
// If given, just assign (cast away const).

rcl/src/rcl/guard_condition_impl.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 cellumation GmbH
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCL__GUARD_CONDITION_IMPL_H_
16+
#define RCL__GUARD_CONDITION_IMPL_H_
17+
18+
#include "rcl/guard_condition.h"
19+
20+
struct rcl_guard_condition_impl_s
21+
{
22+
rmw_guard_condition_t * rmw_handle;
23+
bool allocated_rmw_guard_condition;
24+
rcl_guard_condition_options_t options;
25+
bool in_use_by_waitset;
26+
};
27+
28+
#endif // RCL__GUARD_CONDITION_IMPL_H_

rcl/src/rcl/publisher_impl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#define RCL__PUBLISHER_IMPL_H_
1717

1818
#include "rmw/rmw.h"
19-
2019
#include "rcl/publisher.h"
2120

2221
struct rcl_publisher_impl_s

rcl/src/rcl/service.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,7 @@ extern "C"
3939

4040
#include "./common.h"
4141
#include "./service_event_publisher.h"
42-
43-
struct rcl_service_impl_s
44-
{
45-
rcl_service_options_t options;
46-
rmw_qos_profile_t actual_request_subscription_qos;
47-
rmw_qos_profile_t actual_response_publisher_qos;
48-
rmw_service_t * rmw_handle;
49-
rcl_service_event_publisher_t * service_event_publisher;
50-
char * remapped_service_name;
51-
rosidl_type_hash_t type_hash;
52-
};
42+
#include "./service_impl.h"
5343

5444
rcl_service_t
5545
rcl_get_zero_initialized_service(void)
@@ -189,6 +179,7 @@ rcl_service_init(
189179

190180
// options
191181
service->impl->options = *options;
182+
service->impl->in_use_by_waitset = false;
192183

193184
if (RCL_RET_OK != rcl_node_type_cache_register_type(
194185
node, type_support->get_type_hash_func(type_support),

rcl/src/rcl/service_impl.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2025 cellumation GmbH
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCL__SERVICE_IMPL_H_
16+
#define RCL__SERVICE_IMPL_H_
17+
18+
#include "rmw/rmw.h"
19+
#include "rcl/service.h"
20+
#include "./service_event_publisher.h"
21+
22+
struct rcl_service_impl_s
23+
{
24+
rcl_service_options_t options;
25+
rmw_qos_profile_t actual_request_subscription_qos;
26+
rmw_qos_profile_t actual_response_publisher_qos;
27+
rmw_service_t * rmw_handle;
28+
rcl_service_event_publisher_t * service_event_publisher;
29+
char * remapped_service_name;
30+
rosidl_type_hash_t type_hash;
31+
bool in_use_by_waitset;
32+
};
33+
34+
#endif // RCL__SERVICE_IMPL_H_

rcl/src/rcl/subscription.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ rcl_subscription_init(
103103

104104
// options
105105
subscription->impl->options = *options;
106+
subscription->impl->in_use_by_waitset = false;
106107

107108
// Fill out the implemenation struct.
108109
// TODO(wjwwood): pass allocator once supported in rmw api.

rcl/src/rcl/subscription_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct rcl_subscription_impl_s
2525
rmw_qos_profile_t actual_qos;
2626
rmw_subscription_t * rmw_handle;
2727
rosidl_type_hash_t type_hash;
28+
bool in_use_by_waitset;
2829
};
2930

3031
#endif // RCL__SUBSCRIPTION_IMPL_H_

rcl/src/rcl/timer.c

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,8 @@ extern "C"
2626
#include "rcutils/stdatomic_helper.h"
2727
#include "rcutils/time.h"
2828
#include "tracetools/tracetools.h"
29+
#include "./timer_impl.h"
2930

30-
struct rcl_timer_impl_s
31-
{
32-
// The clock providing time.
33-
rcl_clock_t * clock;
34-
// The associated context.
35-
rcl_context_t * context;
36-
// A guard condition used to wake the associated wait set, either when
37-
// ROSTime causes the timer to expire or when the timer is reset.
38-
rcl_guard_condition_t guard_condition;
39-
// The user supplied callback.
40-
atomic_uintptr_t callback;
41-
// This is a duration in nanoseconds, which is initialized as int64_t
42-
// to be used for internal time calculation.
43-
atomic_int_least64_t period;
44-
// This is a time in nanoseconds since an unspecified time.
45-
atomic_int_least64_t last_call_time;
46-
// This is a time in nanoseconds since an unspecified time.
47-
atomic_int_least64_t next_call_time;
48-
// Credit for time elapsed before ROS time is activated or deactivated.
49-
atomic_int_least64_t time_credit;
50-
// A flag which indicates if the timer is canceled.
51-
atomic_bool canceled;
52-
// The user supplied allocator.
53-
rcl_allocator_t allocator;
54-
// The user supplied on reset callback data.
55-
rcl_timer_on_reset_callback_data_t callback_data;
56-
};
5731

5832
rcl_timer_t
5933
rcl_get_zero_initialized_timer(void)
@@ -177,6 +151,7 @@ rcl_timer_init2(
177151
impl.callback_data.on_reset_callback = NULL;
178152
impl.callback_data.user_data = NULL;
179153
impl.callback_data.reset_counter = 0;
154+
impl.in_use_by_waitset = false;
180155

181156
timer->impl = (rcl_timer_impl_t *)allocator.allocate(sizeof(rcl_timer_impl_t), allocator.state);
182157
if (NULL == timer->impl) {

0 commit comments

Comments
 (0)