-
Notifications
You must be signed in to change notification settings - Fork 90
Description
We tried setting up a scenario where uxr_run_session_time(&session_1, 1000)
is run in one thread, but publishing happens on a separate thread.
while (1)
{
printf("PUB hello\n");
// Session 1 publication
HelloWorld topic_1 = {
count, "Publisher 1 says hello"
};
ucdrBuffer ub_1;
uint32_t topic_size_1 = HelloWorld_size_of_topic(&topic_1, 0);
uxr_prepare_output_stream(&session_1, reliable_out_1, datawriter_id_1, &ub_1, topic_size_1);
HelloWorld_serialize_topic(&ub_1, &topic_1);
sleep(1);
}
This was not publishing to the agent as expected. We discovered that the Mutex acquired in uxr_prepare_output_stream(&session_1, reliable_out_1, datawriter_id_1, &ub_1, topic_size_1);
was never being released. We found the issue in:
uint16_t uxr_prepare_output_stream(
uxrSession* session,
uxrStreamId stream_id,
uxrObjectId entity_id,
ucdrBuffer* ub,
uint32_t len)
{
uint16_t rv = UXR_INVALID_REQUEST_ID;
UXR_LOCK_STREAM_ID(session, stream_id);
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + len;
ub->error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub->error)
{
WRITE_DATA_Payload_Data payload;
rv = uxr_init_base_object_request(&session->info, entity_id, &payload.base);
(void) uxr_serialize_WRITE_DATA_Payload_Data(ub, &payload);
OnFullBuffer on_full_buffer = ub->on_full_buffer;
void* args = ub->args;
ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator));
ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args);
UXR_PREPARE_SHARED_MEMORY(session, entity_id, ub, (uint16_t) len, rv);
}
else
{
UXR_UNLOCK_STREAM_ID(session, stream_id);
}
return rv;
}
The Mutex is only released/unlocked if an error happens. Shouldn't this be released in any case at the end of the function?
Once we removed the else case and just called UXR_UNLOCK_STREAM_ID(session, stream_id);
everytime, then the system operated as expected.
Is there some other reason that the UXR_UNLOCK_STREAM_ID(session, stream_id);
is called only in the else case?
Proposed fix:
uint16_t uxr_prepare_output_stream(
uxrSession* session,
uxrStreamId stream_id,
uxrObjectId entity_id,
ucdrBuffer* ub,
uint32_t len)
{
uint16_t rv = UXR_INVALID_REQUEST_ID;
UXR_LOCK_STREAM_ID(session, stream_id);
size_t payload_size = WRITE_DATA_PAYLOAD_SIZE + len;
ub->error = !uxr_prepare_stream_to_write_submessage(session, stream_id, payload_size, ub, SUBMESSAGE_ID_WRITE_DATA,
FORMAT_DATA);
if (!ub->error)
{
WRITE_DATA_Payload_Data payload;
rv = uxr_init_base_object_request(&session->info, entity_id, &payload.base);
(void) uxr_serialize_WRITE_DATA_Payload_Data(ub, &payload);
OnFullBuffer on_full_buffer = ub->on_full_buffer;
void* args = ub->args;
ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator));
ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args);
UXR_PREPARE_SHARED_MEMORY(session, entity_id, ub, (uint16_t) len, rv);
}
UXR_UNLOCK_STREAM_ID(session, stream_id);
return rv;
}