Skip to content

Commit c05453f

Browse files
authored
Fix publishing on physical data topic (#2581)
* Refs #14124: Create statistics datawriter after enabling the DomainParticipantImpl Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Check whether PDP is enabled before stopping announcement Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Check enable return before creating statistics data writers Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Add regression test for removing not enabled RTPSParticipant Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Add test for deleting not enabled DDS entities Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Apply suggestions Signed-off-by: Eduardo Ponz <[email protected]> * Refs #14124: Apply suggestions Signed-off-by: Eduardo Ponz <[email protected]>
1 parent 0225765 commit c05453f

File tree

9 files changed

+174
-13
lines changed

9 files changed

+174
-13
lines changed

include/fastdds/rtps/builtin/discovery/participant/PDP.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define _FASTDDS_RTPS_PDP_H_
2222
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
2323

24+
#include <atomic>
2425
#include <mutex>
2526
#include <functional>
2627

@@ -97,6 +98,11 @@ class PDP
9798
bool initPDP(
9899
RTPSParticipantImpl* part);
99100

101+
/**
102+
* @brief Enable the Participant Discovery Protocol
103+
*
104+
* @return true if enabled correctly, or if already enabled; false otherwise
105+
*/
100106
bool enable();
101107

102108
virtual bool init(
@@ -402,7 +408,7 @@ class PDP
402408
//!To protect callbacks (ParticipantProxyData&)
403409
std::mutex callback_mtx_;
404410
//!Tell if object is enabled
405-
bool enable_ = false;
411+
std::atomic<bool> enabled_ {false};
406412

407413
/**
408414
* Adds an entry to the collection of participant proxy information.

src/cpp/rtps/builtin/discovery/participant/PDP.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,12 @@ bool PDP::initPDP(
408408

409409
bool PDP::enable()
410410
{
411+
// It is safe to call enable() on already enable PDPs
412+
if (enabled_)
413+
{
414+
return true;
415+
}
416+
411417
// Create lease events on already created proxy data objects
412418
for (ParticipantProxyData* pool_item : participant_proxies_pool_)
413419
{
@@ -430,7 +436,7 @@ bool PDP::enable()
430436

431437
set_initial_announcement_interval();
432438

433-
enable_ = true;
439+
enabled_.store(true);
434440
// Notify "self-discovery"
435441
getRTPSParticipant()->on_entity_discovery(mp_RTPSParticipant->getGuid(),
436442
get_participant_proxy_data(mp_RTPSParticipant->getGuid().guidPrefix)->m_properties);
@@ -443,7 +449,7 @@ void PDP::announceParticipantState(
443449
bool dispose,
444450
WriteParams& wparams)
445451
{
446-
if (enable_)
452+
if (enabled_)
447453
{
448454
// logInfo(RTPS_PDP, "Announcing RTPSParticipant State (new change: " << new_change << ")");
449455
CacheChange_t* change = nullptr;
@@ -543,12 +549,18 @@ void PDP::announceParticipantState(
543549

544550
void PDP::stopParticipantAnnouncement()
545551
{
546-
resend_participant_info_event_->cancel_timer();
552+
if (resend_participant_info_event_)
553+
{
554+
resend_participant_info_event_->cancel_timer();
555+
}
547556
}
548557

549558
void PDP::resetParticipantAnnouncement()
550559
{
551-
resend_participant_info_event_->restart_timer();
560+
if (resend_participant_info_event_)
561+
{
562+
resend_participant_info_event_->restart_timer();
563+
}
552564
}
553565

554566
bool PDP::has_reader_proxy_data(

src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ void PDPClient::announceParticipantState(
410410
bool dispose,
411411
WriteParams& )
412412
{
413-
if (enable_)
413+
if (enabled_)
414414
{
415415
/*
416416
Protect writer sequence number. Make sure in order to prevent AB BA deadlock that the

src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ void PDPServer::announceParticipantState(
538538
bool dispose /* = false */,
539539
WriteParams& )
540540
{
541-
if (enable_)
541+
if (enabled_)
542542
{
543543
logInfo(RTPS_PDP_SERVER,
544544
"Announcing Server " << mp_RTPSParticipant->getGuid() << " (new change: " << new_change << ")");

src/cpp/rtps/builtin/discovery/participant/PDPSimple.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ void PDPSimple::announceParticipantState(
214214
bool dispose,
215215
WriteParams& wp)
216216
{
217-
if (enable_)
217+
if (enabled_)
218218
{
219219
PDP::announceParticipantState(new_change, dispose, wp);
220220

src/cpp/statistics/fastdds/domain/DomainParticipantImpl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,12 @@ ReturnCode_t DomainParticipantImpl::disable_statistics_datawriter(
202202

203203
ReturnCode_t DomainParticipantImpl::enable()
204204
{
205-
create_statistics_builtin_entities();
206205
ReturnCode_t ret = efd::DomainParticipantImpl::enable();
207206

208207
if (ReturnCode_t::RETCODE_OK == ret)
209208
{
210209
rtps_participant_->add_statistics_listener(statistics_listener_, participant_statistics_mask);
210+
create_statistics_builtin_entities();
211211
}
212212

213213
return ret;

src/cpp/statistics/rtps/StatisticsBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ void StatisticsParticipantImpl::on_entity_discovery(
492492
*
493493
*/
494494
auto get_physical_property_value =
495-
[](const dds::ParameterPropertyList_t& properties, const std::string& property_name)
495+
[](const dds::ParameterPropertyList_t& properties, const std::string& property_name) -> std::string
496496
{
497497
auto property = std::find_if(
498498
properties.begin(),
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <gtest/gtest.h>
16+
17+
#include <fastdds/dds/domain/DomainParticipant.hpp>
18+
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
19+
#include <fastdds/dds/domain/qos/DomainParticipantFactoryQos.hpp>
20+
#include <fastdds/dds/domain/qos/DomainParticipantQos.hpp>
21+
#include <fastdds/dds/publisher/DataWriter.hpp>
22+
#include <fastdds/dds/publisher/Publisher.hpp>
23+
#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
24+
#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
25+
#include <fastdds/dds/subscriber/DataReader.hpp>
26+
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
27+
#include <fastdds/dds/subscriber/qos/SubscriberQos.hpp>
28+
#include <fastdds/dds/subscriber/Subscriber.hpp>
29+
#include <fastdds/dds/topic/qos/TopicQos.hpp>
30+
#include <fastdds/dds/topic/Topic.hpp>
31+
#include <fastdds/dds/topic/TypeSupport.hpp>
32+
#include <fastrtps/types/TypesBase.h>
33+
34+
#include "BlackboxTests.hpp"
35+
#include "../types/HelloWorldPubSubTypes.h"
36+
37+
namespace eprosima {
38+
namespace fastdds {
39+
namespace dds {
40+
41+
using ReturnCode_t = eprosima::fastrtps::types::ReturnCode_t;
42+
43+
/**
44+
* This test checks whether it is safe to delete not enabled DDS entities *
45+
*/
46+
TEST(DDSBasic, DeleteDisabledEntities)
47+
{
48+
// Set DomainParticipantFactory to create disabled entities
49+
DomainParticipantFactoryQos factory_qos;
50+
factory_qos.entity_factory().autoenable_created_entities = false;
51+
DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
52+
ASSERT_NE(nullptr, factory);
53+
factory->set_qos(factory_qos);
54+
DomainParticipantFactoryQos factory_qos_check;
55+
ASSERT_EQ(ReturnCode_t::RETCODE_OK, factory->get_qos(factory_qos_check));
56+
ASSERT_EQ(false, factory_qos_check.entity_factory().autoenable_created_entities);
57+
58+
// Create a disabled DomainParticipant, setting it to in turn create disable entities
59+
DomainParticipantQos participant_qos;
60+
participant_qos.entity_factory().autoenable_created_entities = false;
61+
DomainParticipant* participant = factory->create_participant((uint32_t)GET_PID() % 230, participant_qos);
62+
ASSERT_NE(nullptr, participant);
63+
DomainParticipantQos participant_qos_check;
64+
ASSERT_EQ(ReturnCode_t::RETCODE_OK, participant->get_qos(participant_qos_check));
65+
ASSERT_EQ(false, participant_qos_check.entity_factory().autoenable_created_entities);
66+
67+
// Create a disabled Publisher, setting it to in turn create disable entities
68+
PublisherQos publisher_qos;
69+
publisher_qos.entity_factory().autoenable_created_entities = false;
70+
Publisher* publisher = participant->create_publisher(publisher_qos);
71+
ASSERT_NE(nullptr, publisher);
72+
PublisherQos publisher_qos_check;
73+
ASSERT_EQ(ReturnCode_t::RETCODE_OK, publisher->get_qos(publisher_qos_check));
74+
ASSERT_EQ(false, publisher_qos_check.entity_factory().autoenable_created_entities);
75+
76+
// Create a disabled Subscriber, setting it to in turn create disable entities
77+
SubscriberQos subscriber_qos;
78+
subscriber_qos.entity_factory().autoenable_created_entities = false;
79+
Subscriber* subscriber = participant->create_subscriber(subscriber_qos);
80+
ASSERT_NE(nullptr, subscriber);
81+
SubscriberQos subscriber_qos_check;
82+
ASSERT_EQ(ReturnCode_t::RETCODE_OK, subscriber->get_qos(subscriber_qos_check));
83+
ASSERT_EQ(false, subscriber_qos_check.entity_factory().autoenable_created_entities);
84+
85+
// Register type
86+
TypeSupport type_support;
87+
type_support.reset(new HelloWorldPubSubType());
88+
type_support.register_type(participant);
89+
ASSERT_NE(nullptr, type_support);
90+
91+
// Create Topic
92+
Topic* topic = participant->create_topic("HelloWorld", type_support.get_type_name(), TOPIC_QOS_DEFAULT);
93+
ASSERT_NE(nullptr, topic);
94+
95+
// Create a disabled DataWriter
96+
DataWriter* datawriter = publisher->create_datawriter(topic, DATAWRITER_QOS_DEFAULT);
97+
ASSERT_NE(nullptr, datawriter);
98+
99+
// Create a disabled DataReader
100+
DataReader* datareader = subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);
101+
ASSERT_NE(nullptr, datareader);
102+
103+
// Delete all entities
104+
publisher->delete_datawriter(datawriter);
105+
subscriber->delete_datareader(datareader);
106+
participant->delete_publisher(publisher);
107+
participant->delete_subscriber(subscriber);
108+
participant->delete_topic(topic);
109+
factory->delete_participant(participant);
110+
}
111+
112+
} // namespace dds
113+
} // namespace fastdds
114+
} // namespace eprosima

test/blackbox/common/RTPSBlackboxTestsBasic.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,23 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include "BlackboxTests.hpp"
16+
1517
#include <chrono>
1618
#include <thread>
1719

1820
#include <gtest/gtest.h>
1921

20-
#include "BlackboxTests.hpp"
22+
#include <fastrtps/rtps/attributes/RTPSParticipantAttributes.h>
23+
#include <fastrtps/rtps/participant/RTPSParticipant.h>
24+
#include <fastrtps/rtps/RTPSDomain.h>
25+
#include <fastrtps/transport/test_UDPv4TransportDescriptor.h>
26+
#include <fastrtps/xmlparser/XMLProfileManager.h>
2127

2228
#include "RTPSAsSocketReader.hpp"
2329
#include "RTPSAsSocketWriter.hpp"
2430
#include "RTPSWithRegistrationReader.hpp"
2531
#include "RTPSWithRegistrationWriter.hpp"
26-
#include <fastrtps/xmlparser/XMLProfileManager.h>
27-
#include <fastrtps/transport/test_UDPv4TransportDescriptor.h>
2832
#include <rtps/transport/test_UDPv4Transport.h>
2933

3034
using namespace eprosima::fastrtps;
@@ -634,6 +638,31 @@ TEST(RTPS, RTPSNetworkInterfaceChangesAtRunTime)
634638
writer.destroy();
635639
}
636640

641+
/**
642+
* Regression test for checking that a not enabled RTPSParticipant can be removed
643+
*
644+
* https://github.com/eProsima/Fast-DDS/pull/2171 introduced this regression since with it
645+
* the PDP is not enabled until calling BuiltinProtocols::enable(), which is called within
646+
* RTPSParticipant::enable(). However, during RTPSDomain::removeRTPSParticipant(), there is a call
647+
* to BuiltinProtocols::stopRTPSParticipantAnnouncement(), which in turn calls
648+
* PDP::stopRTPSParticipantAnnouncement(). That function ends up accessing a timed event pointer,
649+
* which is only instantiated on PDP::enable(). Since the RTPSParticipant was not enabled,
650+
* BuiltinProtocols and in turn PDP are not either, meaning that it is not safe to call
651+
* PDP::stopRTPSParticipantAnnouncement() on a not enabled PDP.
652+
*
653+
* The test checks that the necessary guards are in place so that it is safe to call
654+
* RTPSDomain::removeRTPSParticipant() o a not enabled RTPSParticipant.
655+
*/
656+
TEST(RTPS, RemoveDisabledParticipant)
657+
{
658+
RTPSParticipantAttributes rtps_attr;
659+
RTPSParticipant* rtps_participant = RTPSDomain::createParticipant(
660+
(uint32_t)GET_PID() % 230, false, rtps_attr, nullptr);
661+
662+
ASSERT_NE(nullptr, rtps_participant);
663+
ASSERT_TRUE(RTPSDomain::removeRTPSParticipant(rtps_participant));
664+
}
665+
637666
#ifdef INSTANTIATE_TEST_SUITE_P
638667
#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w)
639668
#else

0 commit comments

Comments
 (0)