@@ -13,7 +13,11 @@ use crate::{NodeHandle, ENTITY_LIFECYCLE_MUTEX};
13
13
// they are running in. Therefore, this type can be safely sent to another thread.
14
14
unsafe impl Send for rcl_service_t { }
15
15
16
- /// Internal struct used by services.
16
+ /// Manage the lifecycle of an [`rcl_service_t`], including managing its dependencies
17
+ /// on [`rcl_node_t`] and [`rcl_context_t`] by ensuring that these dependencies are
18
+ /// [dropped after][1] the [`rcl_service_t`].
19
+ ///
20
+ /// [1] https://doc.rust-lang.org/reference/destructors.html
17
21
pub struct ServiceHandle {
18
22
rcl_service : Mutex < rcl_service_t > ,
19
23
node_handle : Arc < NodeHandle > ,
@@ -31,7 +35,8 @@ impl Drop for ServiceHandle {
31
35
let rcl_service = self . rcl_service . get_mut ( ) . unwrap ( ) ;
32
36
let mut rcl_node = self . node_handle . rcl_node . lock ( ) . unwrap ( ) ;
33
37
let _lifecycle_lock = ENTITY_LIFECYCLE_MUTEX . lock ( ) . unwrap ( ) ;
34
- // SAFETY: No preconditions for this function
38
+ // SAFETY: The entity lifecycle mutex is locked to protect against the risk of
39
+ // global variables in the rmw implementation being unsafely modified during cleanup.
35
40
unsafe {
36
41
rcl_service_fini ( rcl_service, & mut * rcl_node) ;
37
42
}
@@ -95,21 +100,26 @@ where
95
100
// SAFETY: No preconditions for this function.
96
101
let service_options = unsafe { rcl_service_get_default_options ( ) } ;
97
102
98
- unsafe {
99
- // SAFETY: The rcl_service is zero-initialized as expected by this function.
100
- // The rcl_node is kept alive because it is co-owned by the service.
101
- // The topic name and the options are copied by this function, so they can be dropped
102
- // afterwards.
103
+ {
103
104
let rcl_node = node_handle. rcl_node . lock ( ) . unwrap ( ) ;
104
105
let _lifecycle_lock = ENTITY_LIFECYCLE_MUTEX . lock ( ) . unwrap ( ) ;
105
- rcl_service_init (
106
- & mut rcl_service,
107
- & * rcl_node,
108
- type_support,
109
- topic_c_string. as_ptr ( ) ,
110
- & service_options as * const _ ,
111
- )
112
- . ok ( ) ?;
106
+ unsafe {
107
+ // SAFETY:
108
+ // * The rcl_service is zero-initialized as mandated by this function.
109
+ // * The rcl_node is kept alive by the NodeHandle it is a dependency of the service.
110
+ // * The topic name and the options are copied by this function, so they can be dropped
111
+ // afterwards.
112
+ // * The entity lifecycle mutex is locked to protect against the risk of global
113
+ // variables in the rmw implementation being unsafely modified during initialization.
114
+ rcl_service_init (
115
+ & mut rcl_service,
116
+ & * rcl_node,
117
+ type_support,
118
+ topic_c_string. as_ptr ( ) ,
119
+ & service_options as * const _ ,
120
+ )
121
+ . ok ( ) ?;
122
+ }
113
123
}
114
124
115
125
let handle = Arc :: new ( ServiceHandle {
0 commit comments