Make rcl_client_t have stable location

This prevents another client initializing at the same location.
Therefore preventing conflicts in a trace.
This commit is contained in:
Martin Škoudlil 2025-03-04 14:57:05 +01:00
parent 23672cfdb8
commit e371130cf1
2 changed files with 48 additions and 25 deletions

View File

@ -318,11 +318,10 @@ impl Client_ for UntypedClient_ {
}
}
pub fn create_client_helper(
node: *mut rcl_node_t, service_name: &str, service_ts: *const rosidl_service_type_support_t,
qos_profile: QosProfile,
) -> Result<rcl_client_t> {
let mut client_handle = unsafe { rcl_get_zero_initialized_client() };
pub unsafe fn create_client_helper(
client_handle: &mut rcl_client_t, node: *mut rcl_node_t, service_name: &str,
service_ts: *const rosidl_service_type_support_t, qos_profile: QosProfile,
) -> Result<()> {
let service_name_c_string =
CString::new(service_name).map_err(|_| Error::RCL_RET_INVALID_ARGUMENT)?;
@ -330,15 +329,16 @@ pub fn create_client_helper(
let mut client_options = rcl_client_get_default_options();
client_options.qos = qos_profile.into();
rcl_client_init(
&mut client_handle,
client_handle,
node,
service_ts,
service_name_c_string.as_ptr(),
&client_options,
)
};
if result == RCL_RET_OK as i32 {
Ok(client_handle)
Ok(())
} else {
Err(Error::from_rcl_error(result))
}

View File

@ -849,19 +849,30 @@ impl Node {
where
T: WrappedServiceTypeSupport,
{
let client_handle = create_client_helper(
self.node_handle.as_mut(),
service_name,
T::get_ts(),
qos_profile,
)?;
let ws = TypedClient::<T> {
rcl_handle: client_handle,
// SAFETY: The `rcl_handle` is zero initialized (partial initialization) in this block.
let mut client_arc = Arc::new(Mutex::new(TypedClient::<T> {
rcl_handle: unsafe { rcl_get_zero_initialized_client() },
response_channels: Vec::new(),
poll_available_channels: Vec::new(),
}));
let client_ref = Arc::get_mut(&mut client_arc)
.unwrap() // No other Arc should exist. The Arc was just created.
.get_mut()
.unwrap(); // The mutex was just created. It should not be poisoned.
// SAFETY:
// The client was zero initialized above.
// Full initialization happens in `create_client_helper`.
unsafe {
create_client_helper(
&mut client_ref.rcl_handle,
self.node_handle.as_mut(),
service_name,
T::get_ts(),
qos_profile,
)?;
};
let client_arc = Arc::new(Mutex::new(ws));
let c = make_client(Arc::downgrade(&client_arc));
self.clients.push(client_arc);
Ok(c)
@ -877,20 +888,32 @@ impl Node {
&mut self, service_name: &str, service_type: &str, qos_profile: QosProfile,
) -> Result<ClientUntyped> {
let service_type = UntypedServiceSupport::new_from(service_type)?;
let client_handle = create_client_helper(
self.node_handle.as_mut(),
service_name,
service_type.ts,
qos_profile,
)?;
let client = UntypedClient_ {
// SAFETY: The `rcl_handle` is zero initialized (partial initialization) in this block.
let mut client_arc = Arc::new(Mutex::new(UntypedClient_ {
service_type,
rcl_handle: client_handle,
rcl_handle: unsafe { rcl_get_zero_initialized_client() },
response_channels: Vec::new(),
poll_available_channels: Vec::new(),
}));
let client_ref = Arc::get_mut(&mut client_arc)
.unwrap() // No other Arc should exist. The Arc was just created.
.get_mut()
.unwrap(); // The mutex was just created. It should not be poisoned.
// SAFETY:
// The client was zero initialized above.
// Full initialization happens in `create_client_helper`.
unsafe {
create_client_helper(
&mut client_ref.rcl_handle,
self.node_handle.as_mut(),
service_name,
client_ref.service_type.ts,
qos_profile,
)?;
};
let client_arc = Arc::new(Mutex::new(client));
let c = make_untyped_client(Arc::downgrade(&client_arc));
self.clients.push(client_arc);
Ok(c)