From d277db4a38009796937d8e9c0d6d79b4ff839e74 Mon Sep 17 00:00:00 2001 From: George Joseph <gjoseph@digium.com> Date: Thu, 20 Sep 2018 08:41:15 -0600 Subject: [PATCH] stasis: Add function to delete topic from pool There's been a long standing leak when using topic pools. The topics in the pool get cleaned up when the last pool reference is released but you can't remove a topic specifically. If you reloaded app_voicemail for instance, and mailboxes went away, their topics were left in the pool. * Added stasis_topic_pool_delete_topic() so modules can clean up topics from pools. * Registered the topic pool containers so it can be examined from the CLI when AO2_DEBUG is enabled. They'll be named "<topic_pool_name>-pool". Change-Id: Ib7957951ee5c9b9b4482af7b9b4349112d62bc25 --- include/asterisk/stasis.h | 12 ++++++++++++ main/stasis.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h index bca6d40259..8329dd0924 100644 --- a/include/asterisk/stasis.h +++ b/include/asterisk/stasis.h @@ -752,6 +752,18 @@ struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_t */ struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name); +/*! + * \brief Delete a topic from the topic pool + * + * \param pool Pool from which to delete the topic + * \param topic_name Name of the topic to delete + * + * \since 13.24 + * \since 15.6 + * \since 16.1 + */ +void stasis_topic_pool_delete_topic(struct stasis_topic_pool *pool, const char *topic_name); + /*! * \brief Check if a topic exists in a pool * \param pool Pool to check diff --git a/main/stasis.c b/main/stasis.c index 1616debf3e..c20156f5f6 100644 --- a/main/stasis.c +++ b/main/stasis.c @@ -1079,6 +1079,15 @@ static void topic_pool_dtor(void *obj) { struct stasis_topic_pool *pool = obj; +#ifdef AO2_DEBUG + { + char *container_name = + ast_alloca(strlen(stasis_topic_name(pool->pool_topic)) + strlen("-pool") + 1); + sprintf(container_name, "%s-pool", stasis_topic_name(pool->pool_topic)); + ao2_container_unregister(container_name); + } +#endif + ao2_cleanup(pool->pool_container); pool->pool_container = NULL; ao2_cleanup(pool->pool_topic); @@ -1143,6 +1152,18 @@ static int topic_pool_entry_cmp(void *obj, void *arg, int flags) return CMP_MATCH; } +#ifdef AO2_DEBUG +static void topic_pool_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt) +{ + struct topic_pool_entry *entry = v_obj; + + if (!entry) { + return; + } + prnt(where, "%s", stasis_topic_name(entry->topic)); +} +#endif + struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_topic) { struct stasis_topic_pool *pool; @@ -1158,12 +1179,27 @@ struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_t ao2_cleanup(pool); return NULL; } + +#ifdef AO2_DEBUG + { + char *container_name = + ast_alloca(strlen(stasis_topic_name(pooled_topic)) + strlen("-pool") + 1); + sprintf(container_name, "%s-pool", stasis_topic_name(pooled_topic)); + ao2_container_register(container_name, pool->pool_container, topic_pool_prnt_obj); + } +#endif + ao2_ref(pooled_topic, +1); pool->pool_topic = pooled_topic; return pool; } +void stasis_topic_pool_delete_topic(struct stasis_topic_pool *pool, const char *topic_name) +{ + ao2_find(pool->pool_container, topic_name, OBJ_SEARCH_KEY | OBJ_NODATA | OBJ_UNLINK); +} + struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name) { RAII_VAR(struct topic_pool_entry *, topic_pool_entry, NULL, ao2_cleanup); -- GitLab