Skip to content

Data Race in DataSharingPayloadPool: Inconsistent has_been_removed() State Between release_payload() and advance_till_first_non_removed() #5762

@ZhongXiaozhenzzw

Description

@ZhongXiaozhenzzw

Is there an already existing issue for this?

  • I have searched the existing issues

Expected behavior

If payload->has_been_removed() is true in release_payload(), it should remain true in advance_till_first_non_removed() unless explicitly reset by a well-defined logic. The current behavior indicates a race condition or broken state machine.
Possible Causes

Thread Safety Issue:

    The has_been_removed flag is accessed/modified without proper synchronization (e.g., missing std::atomic or mutex).

Lifecycle Mismanagement:

    The PayloadNode object might be reused or reset incorrectly elsewhere.

Memory Corruption:

    The PayloadNode memory could be corrupted due to concurrent access.

Current behavior

In the DataSharingPayloadPool implementation, we observe an inconsistency in the has_been_removed() state of the same PayloadNode object between two functions:

release_payload():

    payload->has_been_removed() returns true (expected, as the payload is being released).

advance_till_first_non_removed():

    For the same payload object, has_been_removed() suddenly returns false, and the code manually resets it to false via payload->has_been_removed(false).

This suggests a data race or state management bug in the PayloadNode lifecycle.

Code Snippets
bool release_payload(CacheChange_t& cache_change) override {
PayloadNode* payload = PayloadNode::get_from_data(cache_change.serializedPayload.data);
if (payload->has_been_removed()) { // Returns true (expected)
advance_till_first_non_removed();
} else {
free_payloads_.push_back(payload);
}
return DataSharingPayloadPool::release_payload(cache_change);
}

void advance_till_first_non_removed() {
while (descriptor_->notified_begin != descriptor_->notified_end) {
auto payload = static_cast<PayloadNode*>(segment_->get_address_from_offset(offset));
if (!payload->has_been_removed()) { // Returns false (unexpected)
break;
}
payload->has_been_removed(false); // Manually reset to false
free_payloads_.push_back(payload);
}
}

Steps to reproduce

no

Fast DDS version/commit

Fast-DDS Version: 2.10.3

Platform/Architecture

Other. Please specify in Additional context section.

Transport layer

Shared Memory Transport (SHM)

Additional context

Platform: ubuntu22.04

XML configuration file

Relevant log output

Network traffic capture

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageIssue pending classification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions