@@ -3,7 +3,7 @@ use crate::{
3
3
error:: { RclReturnCode , ToResult } ,
4
4
rcl_bindings:: * ,
5
5
wait:: WaitableNumEntities ,
6
- Clock , Node , RclrsError , ENTITY_LIFECYCLE_MUTEX ,
6
+ Clock , DropGuard , Node , RclrsError , ENTITY_LIFECYCLE_MUTEX ,
7
7
} ;
8
8
use rosidl_runtime_rs:: { Action , Message , Service } ;
9
9
use std:: {
@@ -286,43 +286,26 @@ where
286
286
}
287
287
288
288
fn publish_status ( & self ) -> Result < ( ) , RclrsError > {
289
- // We need to hold the lock across this entire method because
290
- // rcl_action_server_get_goal_handles() returns an internal pointer to the
291
- // goal data.
292
- let handle = & * self . handle . lock ( ) ;
293
-
294
- let mut goal_handles = std:: ptr:: null_mut :: < * mut rcl_action_goal_handle_t > ( ) ;
295
- let mut num_goal_handles = 0 ;
296
- unsafe {
297
- // SAFETY: The action server is locked for this entire function, ensuring that the
298
- // goal_handles array remains valid, unless rcl_shutdown is called. However, that is
299
- // outside our control.
300
- rcl_action_server_get_goal_handles ( handle, & mut goal_handles, & mut num_goal_handles)
301
- } . ok ( ) ?;
302
-
303
- let mut goal_statuses = unsafe {
289
+ let mut goal_statuses = DropGuard :: new ( unsafe {
304
290
// SAFETY: No preconditions
305
291
rcl_action_get_zero_initialized_goal_status_array ( )
306
- } ;
292
+ } , |mut goal_status| unsafe {
293
+ // SAFETY: The goal_status array is either zero-initialized and empty or populated by
294
+ // `rcl_action_get_goal_status_array`. In either case, it can be safely finalized.
295
+ rcl_action_goal_status_array_fini ( & mut goal_status) ;
296
+ } ) ;
297
+
307
298
unsafe {
308
299
// SAFETY: The action server is locked through the handle and goal_statuses is
309
300
// zero-initialized.
310
- rcl_action_get_goal_status_array ( handle, & mut goal_statuses)
301
+ rcl_action_get_goal_status_array ( & * self . handle . lock ( ) , & mut * goal_statuses)
311
302
} . ok ( ) ?;
312
- // TODO(nwn): Ensure that rcl_action_goal_status_array_fini() is always called on exit.
313
-
314
- let goal_status_slice = unsafe {
315
- // SAFETY: rcl_action_get_goal_status_array initializes goal_statues.msg.status_list as
316
- // an array of goal statuses with the indicated size. The memory backing this array is
317
- // not modified by anything else during the lifetime of the slice.
318
- std:: slice:: from_raw_parts ( goal_statuses. msg . status_list . data , goal_statuses. msg . status_list . size )
319
- } ;
320
- for goal_status in goal_status_slice {
321
- // Copy into the correct message type to pass to rcl_action_publish_status().
322
- }
323
- // Call rcl_action_publish_status().
324
303
325
- todo ! ( )
304
+ unsafe {
305
+ // SAFETY: The action server is locked through the handle and goal_statuses.msg is a
306
+ // valid `action_msgs__msg__GoalStatusArray` by construction.
307
+ rcl_action_publish_status ( & * self . handle . lock ( ) , & goal_statuses. msg as * const _ as * const std:: ffi:: c_void )
308
+ } . ok ( )
326
309
}
327
310
}
328
311
0 commit comments