Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix get matched publication crash #1853

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/core/ddsc/src/dds_matched.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,28 @@ static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_
return ep;
}

static const struct ddsi_entity_common null_entity_common;

dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih)
{
dds_writer *wr;
if (dds_writer_lock (writer, &wr))
return NULL;

dds_builtintopic_endpoint_t *ret = NULL;
struct ddsi_entity_common *rdc;
struct dds_qos *rdqos;
struct ddsi_entity_common *ppc;
const struct ddsi_entity_common *rdc;
const struct dds_qos *rdqos;
const struct ddsi_entity_common *ppc;

// thread must be "awake" while pointers to DDSI entities are being used
struct ddsi_domaingv * const gv = &wr->m_entity.m_domain->gv;
ddsi_thread_state_awake (ddsi_lookup_thread_state (), gv);
if (ddsi_writer_find_matched_reader (wr->m_wr, ih, &rdc, &rdqos, &ppc))
{
if (ppc == NULL)
ppc = &null_entity_common;
ret = make_builtintopic_endpoint (&rdc->guid, &ppc->guid, ppc->iid, rdqos);
}
ddsi_thread_state_asleep (ddsi_lookup_thread_state ());

dds_writer_unlock (wr);
Expand All @@ -105,15 +111,19 @@ dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t read
return NULL;

dds_builtintopic_endpoint_t *ret = NULL;
struct ddsi_entity_common *wrc;
struct dds_qos *wrqos;
struct ddsi_entity_common *ppc;
const struct ddsi_entity_common *wrc;
const struct dds_qos *wrqos;
const struct ddsi_entity_common *ppc;

// thread must be "awake" while pointers to DDSI entities are being used
struct ddsi_domaingv * const gv = &rd->m_entity.m_domain->gv;
ddsi_thread_state_awake (ddsi_lookup_thread_state (), gv);
if (ddsi_reader_find_matched_writer (rd->m_rd, ih, &wrc, &wrqos, &ppc))
{
if (ppc == NULL)
ppc = &null_entity_common;
ret = make_builtintopic_endpoint (&wrc->guid, &ppc->guid, ppc->iid, wrqos);
}
ddsi_thread_state_asleep (ddsi_lookup_thread_state ());

dds_reader_unlock (rd);
Expand Down
38 changes: 38 additions & 0 deletions src/core/ddsc/tests/builtin_topics.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,41 @@ CU_Test(ddsc_builtin_topics, get_qos)
check_default_qos_of_builtin_entity (tps[i].h, CDQOBE_TOPIC);
}
}

CU_Test(ddsc_builtin_topics, get_matched_publication)
{
static const dds_entity_t tps[] = {
DDS_BUILTIN_TOPIC_DCPSPARTICIPANT,
#ifdef DDS_HAS_TOPIC_DISCOVERY
DDS_BUILTIN_TOPIC_DCPSTOPIC,
#endif
DDS_BUILTIN_TOPIC_DCPSPUBLICATION,
DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION
};
static const dds_guid_t zguid;
// pseudo handles always exist and it actually works even in the absence of a domain
// not sure whether that's a feature or a bug ...
const dds_entity_t dp = dds_create_participant (0, NULL, NULL);
CU_ASSERT_FATAL (dp > 0);
dds_return_t rc;
for (size_t i = 0; i < sizeof (tps) / sizeof (tps[0]); i++)
{
const dds_entity_t rd = dds_create_reader (dp, tps[i], NULL, NULL);
CU_ASSERT_FATAL (rd > 0);
dds_instance_handle_t wrih;
// Application may not create writers, one local orphan writer, no remote writers
// Function returns actual number of matches, even if greater than the size of the
// output array.
rc = dds_get_matched_publications (rd, &wrih, 1);
CU_ASSERT_FATAL (rc == 1);
dds_builtintopic_endpoint_t *ep = dds_get_matched_publication_data (rd, wrih);
CU_ASSERT_FATAL (ep != NULL);
CU_ASSERT_FATAL (memcmp (&ep->participant_key, &zguid, sizeof (ep->participant_key)) == 0);
CU_ASSERT_FATAL (ep->participant_instance_handle == 0);
dds_builtintopic_free_endpoint (ep);
rc = dds_delete (rd);
CU_ASSERT_FATAL (rc == 0);
}
rc = dds_delete (dp);
CU_ASSERT_FATAL (rc == 0);
}
30 changes: 26 additions & 4 deletions src/core/ddsi/include/dds/ddsi/ddsi_endpoint_match.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,33 @@ dds_return_t ddsi_writer_get_matched_subscriptions (struct ddsi_writer *wr, uint
/** @component endpoint_matching */
dds_return_t ddsi_reader_get_matched_publications (struct ddsi_reader *rd, uint64_t *wrs, size_t nwrs);

/** @component endpoint_matching */
bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struct ddsi_entity_common **rdc, struct dds_qos **rdqos, struct ddsi_entity_common **ppc);
/** @brief Lookup the instance handle of a matching reader and return it, it's qos and participant
* @component endpoint_matching
*
* @note Thread state must be "awake", returned pointers are aliases; lifetime ends on leaving the "awake" state; contents may not be modified.
*
* @param[in] wr writer for which to lookup ih in the setting of matching readers
* @param[in] ih instance handle of a reader
* @param[out] rdc pointer to the common entity data of the reader
* @param[out] rdqos pointer to the QoS of the reader
* @param[out] ppc participant, may be null for an orphan reader
* @return true iff ih corresponds to a matched reader, output parameters are undefined if not
*/
bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, const struct ddsi_entity_common **rdc, const struct dds_qos **rdqos, const struct ddsi_entity_common **ppc);

/** @component endpoint_matching */
bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struct ddsi_entity_common **wrc, struct dds_qos **wrqos, struct ddsi_entity_common **ppc);
/** @brief Lookup the instance handle of a matching writer and return it, it's qos and participant
* @component endpoint_matching
*
* @note Thread state must be "awake", returned pointers are aliases; lifetime ends on leaving the "awake" state; contents may not be modified.
*
* @param[in] rd reader for which to lookup ih in the setting of matching writers
* @param[in] ih instance handle of a writer
* @param[out] wrc pointer to the common entity data of the writer
* @param[out] wrqos pointer to the QoS of the writer
* @param[out] ppc participant, may be null for an orphan writer
* @return true iff ih corresponds to a matched writer, output parameters are undefined if not
*/
bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, const struct ddsi_entity_common **wrc, const struct dds_qos **wrqos, const struct ddsi_entity_common **ppc);

#if defined (__cplusplus)
}
Expand Down
10 changes: 6 additions & 4 deletions src/core/ddsi/src/ddsi_endpoint_match.c
Original file line number Diff line number Diff line change
Expand Up @@ -1864,7 +1864,7 @@ dds_return_t ddsi_reader_get_matched_publications (struct ddsi_reader *rd, uint6
return (dds_return_t) nwrs_act;
}

bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struct ddsi_entity_common **rdc, struct dds_qos **rdqos, struct ddsi_entity_common **ppc)
bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, const struct ddsi_entity_common **rdc, const struct dds_qos **rdqos, const struct ddsi_entity_common **ppc)
{
/* FIXME: this ought not be so inefficient */
struct ddsi_domaingv *gv = wr->e.gv;
Expand Down Expand Up @@ -1895,14 +1895,15 @@ bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struc
found = true;
*rdc = &rd->e;
*rdqos = rd->xqos;
*ppc = &rd->c.pp->e;
// The day orphan readers are introduced in addition to orphan writers, rd->c.pp may be a null pointer
*ppc = rd->c.pp ? &rd->c.pp->e : NULL;
}
}
ddsrt_mutex_unlock (&wr->e.lock);
return found;
}

bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struct ddsi_entity_common **wrc, struct dds_qos **wrqos, struct ddsi_entity_common **ppc)
bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, const struct ddsi_entity_common **wrc, const struct dds_qos **wrqos, const struct ddsi_entity_common **ppc)
{
/* FIXME: this ought not be so inefficient */
struct ddsi_domaingv *gv = rd->e.gv;
Expand Down Expand Up @@ -1933,7 +1934,8 @@ bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struc
found = true;
*wrc = &wr->e;
*wrqos = wr->xqos;
*ppc = &wr->c.pp->e;
// Orphan writers have no participant
*ppc = wr->c.pp ? &wr->c.pp->e : NULL;
}
}
ddsrt_mutex_unlock (&rd->e.lock);
Expand Down
Loading