Limit entities in waitset to those in same "scope"

Require that all entities attached to waitset are in the same
participant (if the waitset's parent is a participant) or in the same
domain (if the waitset's parent is a domain).  There used to be no check
on this, but it always seemed unhygenic and now that domains and the
entire library instantiation can be used as parents, it seems much
better to enforce this scoping rule.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-08-28 15:35:06 +02:00 committed by eboasson
parent 6da50bdbae
commit 705b03cf09
4 changed files with 65 additions and 0 deletions

View file

@ -80,6 +80,7 @@ DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_s
DDS_EXPORT dds_participant *dds_entity_participant (dds_entity *e); DDS_EXPORT dds_participant *dds_entity_participant (dds_entity *e);
DDS_EXPORT void dds_entity_final_deinit_before_free (dds_entity *e); DDS_EXPORT void dds_entity_final_deinit_before_free (dds_entity *e);
DDS_EXPORT bool dds_entity_in_scope (const dds_entity *e, const dds_entity *root);
DDS_EXPORT dds_return_t DDS_EXPORT dds_return_t
dds_entity_pin ( dds_entity_pin (

View file

@ -398,6 +398,14 @@ static dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state
return (parent_handle != 0) ? dds_delete_impl (parent_handle, DIS_IMPLICIT, parent_iid) : DDS_RETCODE_OK; return (parent_handle != 0) ? dds_delete_impl (parent_handle, DIS_IMPLICIT, parent_iid) : DDS_RETCODE_OK;
} }
bool dds_entity_in_scope (const dds_entity *e, const dds_entity *root)
{
/* An entity is not an ancestor of itself */
while (e != NULL && e != root)
e = e->m_parent;
return (e != NULL);
}
dds_entity_t dds_get_parent (dds_entity_t entity) dds_entity_t dds_get_parent (dds_entity_t entity)
{ {
dds_entity *e; dds_entity *e;

View file

@ -247,6 +247,16 @@ dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_
else if ((ret = dds_entity_pin (entity, &e)) < 0) else if ((ret = dds_entity_pin (entity, &e)) < 0)
goto err_waitset; goto err_waitset;
/* Entity must be "in scope": within the participant, domain or (self-evidently true) Cyclone DDS,
depending on the parent of the waitset, so that one can't use a waitset created in participant
A to wait for entities in participant B, &c. While there is no technical obstacle (though
there might be one for cross-domain use one day), it seems rather unhygienic practice. */
if (!dds_entity_in_scope (e, ws->m_entity.m_parent))
{
ret = DDS_RETCODE_BAD_PARAMETER;
goto err_entity;
}
/* This will fail if given entity is already attached (or deleted). */ /* This will fail if given entity is already attached (or deleted). */
if ((ret = dds_entity_observer_register (e, &ws->m_entity, dds_waitset_observer, dds_waitset_delete_observer)) != DDS_RETCODE_OK) if ((ret = dds_entity_observer_register (e, &ws->m_entity, dds_waitset_observer, dds_waitset_delete_observer)) != DDS_RETCODE_OK)
goto err_entity; goto err_entity;

View file

@ -351,6 +351,52 @@ CU_Test(ddsc_waitset_attach, deleted_waitset, .init=ddsc_waitset_basic_init, .fi
} }
/*************************************************************************************************/ /*************************************************************************************************/
/*************************************************************************************************/
CU_TheoryDataPoints(ddsc_waitset_attach, scoping) = {
CU_DataPoints (int, -9, -1, -2, 0, 0, 2), /* owner: -9: lib, -1: dom0, -2: dom1 */
CU_DataPoints (int, 0, 0, 2, 0, 0, 2), /* ok1: participant one can attach */
CU_DataPoints (int, 3, 1, 3, -1, -1, -1), /* ok2: other participant one can attach, or -1 */
CU_DataPoints (int, -1, 2, 0, 1, 2, 0), /* fail: participant that one cannot attach, or -1 */
};
CU_Theory ((int owner, int ok1, int ok2, int fail), ddsc_waitset_attach, scoping)
{
dds_entity_t par[4], dom[2], ws, ownh;
dds_return_t rc;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
par[2*i+j] = dds_create_participant ((dds_domainid_t) i, NULL, NULL);
CU_ASSERT_FATAL (par[2*i+j] > 0);
}
dom[i] = dds_get_parent (par[2*i]);
CU_ASSERT_FATAL (dom[i] > 0);
}
if (owner == -9) {
ownh = DDS_CYCLONEDDS_HANDLE;
} else if (owner < 0) {
ownh = dom[-owner - 1];
} else {
ownh = par[owner];
}
printf ("%d %d %d %d | %"PRId32"\n", owner, ok1, ok2, fail, ownh);
ws = dds_create_waitset (ownh);
CU_ASSERT_FATAL (ws > 0);
rc = dds_waitset_attach (ws, par[ok1], 0);
CU_ASSERT_FATAL (rc == 0);
if (ok2 >= 0) {
rc = dds_waitset_attach (ws, par[ok2], 1);
CU_ASSERT_FATAL (rc == 0);
}
if (fail >= 0) {
rc = dds_waitset_attach (ws, par[fail], 2);
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
}
rc = dds_delete (DDS_CYCLONEDDS_HANDLE);
CU_ASSERT_FATAL (rc == 0);
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
}
/*************************************************************************************************/
/************************************************************************************************** /**************************************************************************************************