@@ -11,10 +11,15 @@ use parking_lot::Mutex;
11
11
12
12
impl Drop for rcl_context_t {
13
13
fn drop ( & mut self ) {
14
- // SAFETY: These functions have no preconditions besides a valid/initialized handle
15
14
unsafe {
16
- rcl_shutdown ( self ) ;
17
- rcl_context_fini ( self ) ;
15
+ // The context may be invalid when rcl_init failed, e.g. because of invalid command
16
+ // line arguments.
17
+ // SAFETY: No preconditions for this function.
18
+ if rcl_context_is_valid ( self ) {
19
+ // SAFETY: These functions have no preconditions besides a valid handle
20
+ rcl_shutdown ( self ) ;
21
+ rcl_context_fini ( self ) ;
22
+ }
18
23
}
19
24
}
20
25
}
@@ -54,47 +59,44 @@ impl Context {
54
59
/// # Panics
55
60
/// When there is an interior null byte in any of the args.
56
61
pub fn new ( args : impl IntoIterator < Item = String > ) -> Result < Self , RclReturnCode > {
57
- let context = Self {
58
- // SAFETY: Getting a zero-initialized value is always safe
59
- handle : Arc :: new ( Mutex :: new ( unsafe { rcl_get_zero_initialized_context ( ) } ) ) ,
60
- } ;
62
+ // SAFETY: Getting a zero-initialized value is always safe
63
+ let mut rcl_context = unsafe { rcl_get_zero_initialized_context ( ) } ;
61
64
let cstring_args: Vec < CString > = args
62
65
. into_iter ( )
63
66
. map ( |arg| CString :: new ( arg) . unwrap ( ) )
64
67
. collect ( ) ;
65
68
// Vector of pointers into cstring_args
66
69
let c_args: Vec < * const c_char > = cstring_args. iter ( ) . map ( |arg| arg. as_ptr ( ) ) . collect ( ) ;
67
- // Scope for the handle
68
- {
69
- let handle = & mut * context. handle . lock ( ) ;
70
- unsafe {
71
- // SAFETY: No preconditions for this function.
72
- let allocator = rcutils_get_default_allocator ( ) ;
73
- // SAFETY: Getting a zero-initialized value is always safe.
74
- let mut init_options = rcl_get_zero_initialized_init_options ( ) ;
75
- // SAFETY: Passing in a zero-initialized value is expected.
76
- // In the case where this returns not ok, there's nothing to clean up.
77
- rcl_init_options_init ( & mut init_options, allocator) . ok ( ) ?;
78
- // SAFETY: This function does not store the ephemeral init_options and c_args
79
- // pointers. Passing in a zero-initialized handle is expected.
80
- let ret = rcl_init (
81
- c_args. len ( ) as i32 ,
82
- if c_args. is_empty ( ) {
83
- std:: ptr:: null ( )
84
- } else {
85
- c_args. as_ptr ( )
86
- } ,
87
- & init_options,
88
- handle,
89
- ) ;
90
- // SAFETY: It's safe to pass in an initialized object.
91
- // Early return will not leak memory, because this is the last fini function.
92
- rcl_init_options_fini ( & mut init_options) . ok ( ) ?;
93
- // Move the check after the last fini()
94
- ret. ok ( ) ?;
95
- }
70
+ unsafe {
71
+ // SAFETY: No preconditions for this function.
72
+ let allocator = rcutils_get_default_allocator ( ) ;
73
+ // SAFETY: Getting a zero-initialized value is always safe.
74
+ let mut init_options = rcl_get_zero_initialized_init_options ( ) ;
75
+ // SAFETY: Passing in a zero-initialized value is expected.
76
+ // In the case where this returns not ok, there's nothing to clean up.
77
+ rcl_init_options_init ( & mut init_options, allocator) . ok ( ) ?;
78
+ // SAFETY: This function does not store the ephemeral init_options and c_args
79
+ // pointers. Passing in a zero-initialized handle is expected.
80
+ let ret = rcl_init (
81
+ c_args. len ( ) as i32 ,
82
+ if c_args. is_empty ( ) {
83
+ std:: ptr:: null ( )
84
+ } else {
85
+ c_args. as_ptr ( )
86
+ } ,
87
+ & init_options,
88
+ & mut rcl_context,
89
+ )
90
+ . ok ( ) ;
91
+ // SAFETY: It's safe to pass in an initialized object.
92
+ // Early return will not leak memory, because this is the last fini function.
93
+ rcl_init_options_fini ( & mut init_options) . ok ( ) ?;
94
+ // Move the check after the last fini()
95
+ ret?;
96
96
}
97
- Ok ( context)
97
+ Ok ( Self {
98
+ handle : Arc :: new ( Mutex :: new ( rcl_context) ) ,
99
+ } )
98
100
}
99
101
100
102
/// Creates a node.
0 commit comments