summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Bright <sean.bright@gmail.com>2017-03-29 11:11:51 -0400
committerSean Bright <sean.bright@gmail.com>2017-03-30 13:59:11 -0400
commit5c1ea3ebbd17b7e409b3531d7b1a9b7615611c4a (patch)
treef30ae9b24f11549b0baff717b929fd11059e9861
parent7ac5a33920bae82188c0d7aae97ce0e3979f2f22 (diff)
astobj2: Prevent potential deadlocks with ao2_global_obj_release
The ao2_global_obj_release() function holds an exclusive lock on the global object while it is being dereferenced. Any destructors that run during this time that call ao2_global_obj_ref() will deadlock because a read lock is required. Instead, we make the global object inaccessible inside of the write lock and only dereference it once we have released the lock. This allows the affected destructors to fail gracefully. While this doesn't completely solve the referenced issue (the error message about not being able to create an IQ continues to be shown) it does solve the backtrace spew that accompanied it. ASTERISK-21009 #close Reported by: Marcello Ceschia Change-Id: Idf40ae136b5070dba22cb576ea8414fbc9939385
-rw-r--r--include/asterisk/astobj2.h6
-rw-r--r--main/astobj2.c24
2 files changed, 2 insertions, 28 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 28ae73e87..484e1e35c 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -854,11 +854,9 @@ struct ao2_global_obj {
* \return Nothing
*/
#define ao2_t_global_obj_release(holder, tag) \
- __ao2_global_obj_release(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
+ __ao2_global_obj_replace_unref(&holder, NULL, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
#define ao2_global_obj_release(holder) \
- __ao2_global_obj_release(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-
-void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name);
+ __ao2_global_obj_replace_unref(&holder, NULL, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
/*!
* \brief Replace an ao2 object in the global holder.
diff --git a/main/astobj2.c b/main/astobj2.c
index 1529e91b0..d534900dd 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -729,30 +729,6 @@ unsigned int ao2_options_get(void *obj)
return orig_obj->priv_data.options;
}
-
-void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
-{
- if (!holder) {
- /* For sanity */
- ast_log(LOG_ERROR, "Must be called with a global object!\n");
- ast_assert(0);
- return;
- }
- if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
- /* Could not get the write lock. */
- ast_assert(0);
- return;
- }
-
- /* Release the held ao2 object. */
- if (holder->obj) {
- __ao2_ref(holder->obj, -1, tag, file, line, func);
- holder->obj = NULL;
- }
-
- __ast_rwlock_unlock(file, line, func, &holder->lock, name);
-}
-
void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name)
{
void *obj_old;