@@ -13,7 +13,11 @@ use crate::{NodeHandle, ENTITY_LIFECYCLE_MUTEX};
1313// they are running in. Therefore, this type can be safely sent to another thread.
1414unsafe impl Send for rcl_service_t { }
1515
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
1721pub struct ServiceHandle {
1822 rcl_service : Mutex < rcl_service_t > ,
1923 node_handle : Arc < NodeHandle > ,
@@ -31,7 +35,8 @@ impl Drop for ServiceHandle {
3135 let rcl_service = self . rcl_service . get_mut ( ) . unwrap ( ) ;
3236 let mut rcl_node = self . node_handle . rcl_node . lock ( ) . unwrap ( ) ;
3337 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.
3540 unsafe {
3641 rcl_service_fini ( rcl_service, & mut * rcl_node) ;
3742 }
@@ -95,21 +100,26 @@ where
95100 // SAFETY: No preconditions for this function.
96101 let service_options = unsafe { rcl_service_get_default_options ( ) } ;
97102
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+ {
103104 let rcl_node = node_handle. rcl_node . lock ( ) . unwrap ( ) ;
104105 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+ }
113123 }
114124
115125 let handle = Arc :: new ( ServiceHandle {
0 commit comments