Explicitly check CLOSED flag when creating entity

All functions creating an entity pin the parent, which guarantees that
the CLOSED is not set yet, but as setting it occurs within the mutex, it
may be set by the time the parent has been locked.  One should not try
to add a child entity at that point, so check it again.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-08-30 15:27:05 +02:00 committed by eboasson
parent c0aad847fb
commit 78c255d432
11 changed files with 51 additions and 17 deletions

View file

@ -36,7 +36,7 @@ dds_entity_register_child (
DDS_EXPORT void DDS_EXPORT void
dds_entity_add_ref_locked(dds_entity *e); dds_entity_add_ref_locked(dds_entity *e);
#define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \ #define DEFINE_ENTITY_LOCK_UNLOCK_ONLY(qualifier_, type_, kind_) \
qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x) \ qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x) \
{ \ { \
dds_return_t rc; \ dds_return_t rc; \
@ -46,15 +46,29 @@ dds_entity_add_ref_locked(dds_entity *e);
*x = (type_ *) e; \ *x = (type_ *) e; \
return DDS_RETCODE_OK; \ return DDS_RETCODE_OK; \
} \ } \
\
qualifier_ void type_##_unlock (type_ *x) \ qualifier_ void type_##_unlock (type_ *x) \
{ \ { \
dds_entity_unlock (&x->m_entity); \ dds_entity_unlock (&x->m_entity); \
} }
#define DECL_ENTITY_LOCK_UNLOCK(qualifier_, type_) \ #define DECL_ENTITY_LOCK_UNLOCK_ONLY(qualifier_, type_) \
qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x); \ qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x); \
qualifier_ void type_##_unlock (type_ *x); qualifier_ void type_##_unlock (type_ *x);
#define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \
DEFINE_ENTITY_LOCK_UNLOCK_ONLY (qualifier_, type_, kind_) \
qualifier_ dds_return_t type_##_lock_for_create (dds_entity_t hdl, type_ **x) \
{ \
dds_return_t rc; \
dds_entity *e; \
if ((rc = dds_entity_lock_for_create (hdl, kind_, &e)) < 0) \
return rc; \
*x = (type_ *) e; \
return DDS_RETCODE_OK; \
}
#define DECL_ENTITY_LOCK_UNLOCK(qualifier_, type_) \
DECL_ENTITY_LOCK_UNLOCK_ONLY (qualifier_, type_) \
qualifier_ dds_return_t type_##_lock_for_create (dds_entity_t hdl, type_ **x);
DDS_EXPORT inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink) { DDS_EXPORT inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink) {
return (dds_entity *) ((char *) hdllink - offsetof (struct dds_entity, m_hdllink)); return (dds_entity *) ((char *) hdllink - offsetof (struct dds_entity, m_hdllink));
} }
@ -96,6 +110,12 @@ dds_entity_lock(
dds_entity_kind_t kind, dds_entity_kind_t kind,
dds_entity **e); dds_entity **e);
DDS_EXPORT dds_return_t
dds_entity_lock_for_create(
dds_entity_t hdl,
dds_entity_kind_t kind,
dds_entity **e);
DDS_EXPORT void DDS_EXPORT void
dds_entity_unlock(dds_entity *e); dds_entity_unlock(dds_entity *e);

View file

@ -1099,6 +1099,20 @@ dds_return_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_enti
} }
} }
dds_return_t dds_entity_lock_for_create (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr)
{
dds_return_t res;
if ((res = dds_entity_lock (hdl, kind, eptr)) < 0)
return res;
else if (!dds_handle_is_closed (&(*eptr)->m_hdllink))
return DDS_RETCODE_OK;
else
{
ddsrt_mutex_unlock (&(*eptr)->m_mutex);
return DDS_RETCODE_BAD_PARAMETER;
}
}
void dds_entity_unlock (dds_entity *e) void dds_entity_unlock (dds_entity *e)
{ {
ddsrt_mutex_unlock (&e->m_mutex); ddsrt_mutex_unlock (&e->m_mutex);

View file

@ -41,7 +41,7 @@ dds_entity_t dds_create_guardcondition (dds_entity_t owner)
if ((rc = dds_init ()) < 0) if ((rc = dds_init ()) < 0)
return rc; return rc;
if ((rc = dds_entity_lock (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) if ((rc = dds_entity_lock_for_create (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
goto err_entity_lock; goto err_entity_lock;
switch (dds_entity_kind (e)) switch (dds_entity_kind (e))

View file

@ -52,7 +52,7 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo
dds_qos_t *new_qos; dds_qos_t *new_qos;
dds_return_t ret; dds_return_t ret;
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) if ((ret = dds_participant_lock_for_create (participant, &par)) != DDS_RETCODE_OK)
return ret; return ret;
new_qos = dds_create_qos (); new_qos = dds_create_qos ();

View file

@ -26,7 +26,7 @@ dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_
dds_return_t rc; dds_return_t rc;
dds_reader *r; dds_reader *r;
if ((rc = dds_reader_lock (reader, &r)) != DDS_RETCODE_OK) if ((rc = dds_reader_lock_for_create (reader, &r)) != DDS_RETCODE_OK)
return rc; return rc;
else else
{ {

View file

@ -64,7 +64,7 @@ dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask)
{ {
dds_reader *rd; dds_reader *rd;
dds_return_t rc; dds_return_t rc;
if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) if ((rc = dds_reader_lock_for_create (reader, &rd)) != DDS_RETCODE_OK)
return rc; return rc;
else else
{ {

View file

@ -323,7 +323,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
} }
} }
if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) if ((ret = dds_subscriber_lock_for_create (subscriber, &sub)) != DDS_RETCODE_OK)
{ {
reader = ret; reader = ret;
goto err_sub_lock; goto err_sub_lock;
@ -335,7 +335,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
} }
if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK) if ((ret = dds_topic_lock_for_create (t, &tp)) != DDS_RETCODE_OK)
{ {
reader = ret; reader = ret;
goto err_tp_lock; goto err_tp_lock;
@ -397,7 +397,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
ddsrt_mutex_lock (&tp->m_entity.m_mutex); ddsrt_mutex_lock (&tp->m_entity.m_mutex);
assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
thread_state_asleep (lookup_thread_state ()); thread_state_asleep (lookup_thread_state ());
rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_domain->gv, &rd->m_entity.m_guid); rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_domain->gv, &rd->m_entity.m_guid);
dds_entity_register_child (&sub->m_entity, &rd->m_entity); dds_entity_register_child (&sub->m_entity, &rd->m_entity);

View file

@ -74,7 +74,7 @@ dds_entity_t dds_create_subscriber (dds_entity_t participant, const dds_qos_t *q
dds_participant *par; dds_participant *par;
dds_entity_t hdl; dds_entity_t hdl;
dds_return_t ret; dds_return_t ret;
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) if ((ret = dds_participant_lock_for_create (participant, &par)) != DDS_RETCODE_OK)
return ret; return ret;
hdl = dds__create_subscriber_l (par, qos, listener); hdl = dds__create_subscriber_l (par, qos, listener);
dds_participant_unlock (par); dds_participant_unlock (par);

View file

@ -324,7 +324,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
/* FIXME: just mutex_lock ought to be good enough, but there is the /* FIXME: just mutex_lock ought to be good enough, but there is the
pesky "closed" check still ... */ pesky "closed" check still ... */
if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) if ((rc = dds_participant_lock_for_create (participant, &par)) != DDS_RETCODE_OK)
goto err_lock_participant; goto err_lock_participant;
bool retry_lookup; bool retry_lookup;
@ -384,7 +384,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
abort (); abort ();
} }
if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) if ((rc = dds_participant_lock_for_create (participant, &par)) != DDS_RETCODE_OK)
goto err_lock_participant; goto err_lock_participant;
} }
} while (retry_lookup); } while (retry_lookup);

View file

@ -21,7 +21,7 @@
#include "dds__rhc.h" #include "dds__rhc.h"
#include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_iid.h"
DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET) DEFINE_ENTITY_LOCK_UNLOCK_ONLY (static, dds_waitset, DDS_KIND_WAITSET)
static bool is_triggered (struct dds_entity *e) static bool is_triggered (struct dds_entity *e)
{ {
@ -125,7 +125,7 @@ dds_entity_t dds_create_waitset (dds_entity_t owner)
if ((rc = dds_init ()) < 0) if ((rc = dds_init ()) < 0)
return rc; return rc;
if ((rc = dds_entity_lock (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) if ((rc = dds_entity_lock_for_create (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
goto err_entity_lock; goto err_entity_lock;
switch (dds_entity_kind (e)) switch (dds_entity_kind (e))

View file

@ -261,14 +261,14 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
dds_entity_unpin (p_or_p); dds_entity_unpin (p_or_p);
} }
if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK) if ((rc = dds_publisher_lock_for_create (publisher, &pub)) != DDS_RETCODE_OK)
return rc; return rc;
ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.data_conn_uc; ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.data_conn_uc;
if (publisher != participant_or_publisher) if (publisher != participant_or_publisher)
pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK) if ((rc = dds_topic_lock_for_create (topic, &tp)) != DDS_RETCODE_OK)
goto err_tp_lock; goto err_tp_lock;
assert (tp->m_stopic); assert (tp->m_stopic);