Skip to content

Probabilistic exception (nullptr access to RTPSReader listener) when deleting a DataReader #3303

Open
@i-and

Description

@i-and

Is there an already existing issue for this?

  • I have searched the existing issues

Expected behavior

The destruction of DDS entities is performed correctly

Current behavior

Access by nullptr pointer

Steps to reproduce

Developed a separate test consisting of one DataReader and one DataWriter (each runs in a separate application). On the part of the DataWriter, the partition name is changed every 2-5 ms to ensure that the discovery mechanism is triggered with a high frequency. The running DataReader is created and deleted every 10/100 ms.

Fast DDS version/commit

2.9.1

Platform/Architecture

Ubuntu Focal 20.04 amd64

Transport layer

UDPv4

Additional context

Nullptr access occurs when one of the methods onReaderMatched(...) is called in the file EDP.cpp

//MATCHED AND ADDED CORRECTLY:
if (r.getListener() != nullptr)
{
  MatchingInfo info;
  info.status = MATCHED_MATCHING;
  info.remoteEndpointGuid = writer_guid;
  r.getListener()->onReaderMatched(&r, info);

  const SubscriptionMatchedStatus& sub_info =
       update_subscription_matched_status(readerGUID, writer_guid, 1);
  r.getListener()->onReaderMatched(&r, sub_info);
}

Code analysis showed that the reason for the error is race condition when accessing the pointer to the RTPS listener in EDP against the background of the ~DataReaderImpl() destructor, which performs an unsecured reset of the RTPS listener in the disable() method:

void DataReaderImpl::disable()
{
    set_listener(nullptr);
    if (reader_ != nullptr)
    {
        reader_->setListener(nullptr);
    }
}

The proposed fix is to exclude the disable() call in the destructor so that it looks like this:

DataReaderImpl::~DataReaderImpl()
{
    // assert there are no pending conditions
    assert(read_conditions_.empty());

    // Disable the datareader to prevent receiving data in the middle of deleting it
    // disable();

    stop();

    delete user_datareader_;
}

In this case, all the necessary locks are provided during the execution of the RTPSParticipantImpl::deleteUserEndpoint() method. At the same time, the test also stopped giving an execution error.

XML configuration file

No response

Relevant log output

No response

Network traffic capture

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue to report a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions