diff --git a/main/format.c b/main/format.c index 1c60ab77039ab7499034139582e602fd1ffe293f..a365ab0d580e88e0fc95b14a389aaa172a86be5a 100644 --- a/main/format.c +++ b/main/format.c @@ -106,7 +106,7 @@ int ast_format_get_video_mark(const struct ast_format *format) return format->fattr.rtp_marker_bit; } -static int has_interface(const struct ast_format *format) +static struct interface_ao2_wrapper *find_interface(const struct ast_format *format) { struct interface_ao2_wrapper *wrapper; struct interface_ao2_wrapper tmp_wrapper = { @@ -114,30 +114,22 @@ static int has_interface(const struct ast_format *format) }; ast_rwlock_rdlock(&ilock); - if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) { - ast_rwlock_unlock(&ilock); - return 0; - } + wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)); ast_rwlock_unlock(&ilock); - ao2_ref(wrapper, -1); - return 1; + + return wrapper; } -static struct interface_ao2_wrapper *find_interface(const struct ast_format *format) +static int has_interface(const struct ast_format *format) { struct interface_ao2_wrapper *wrapper; - struct interface_ao2_wrapper tmp_wrapper = { - .id = format->id, - }; - ast_rwlock_rdlock(&ilock); - if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) { - ast_rwlock_unlock(&ilock); - return NULL; + wrapper = find_interface(format); + if (!wrapper) { + return 0; } - ast_rwlock_unlock(&ilock); - - return wrapper; + ao2_ref(wrapper, -1); + return 1; } /*! \internal @@ -1050,7 +1042,7 @@ static int format_list_init(void) return 0; } -int ast_format_list_init() +int ast_format_list_init(void) { if (ast_rwlock_init(&format_list_array_lock)) { return -1; @@ -1073,7 +1065,7 @@ init_list_cleanup: return -1; } -int ast_format_attr_init() +int ast_format_attr_init(void) { ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis)); if (ast_rwlock_init(&ilock)) { @@ -1081,7 +1073,6 @@ int ast_format_attr_init() } if (!(interfaces = ao2_container_alloc(283, interface_hash_cb, interface_cmp_cb))) { - ast_rwlock_destroy(&ilock); goto init_cleanup; } return 0; @@ -1316,17 +1307,23 @@ int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interf .id = interface->id, }; - /* check for duplicates first*/ + /* + * Grab the write lock before checking for duplicates in + * anticipation of adding a new interface and to prevent a + * duplicate from sneaking in between the check and add. + */ ast_rwlock_wrlock(&ilock); + + /* check for duplicates first*/ if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) { ast_rwlock_unlock(&ilock); ast_log(LOG_WARNING, "Can not register attribute interface for format id %d, interface already exists.\n", interface->id); ao2_ref(wrapper, -1); return -1; } - ast_rwlock_unlock(&ilock); if (!(wrapper = ao2_alloc(sizeof(*wrapper), interface_destroy_cb))) { + ast_rwlock_unlock(&ilock); return -1; } @@ -1334,9 +1331,8 @@ int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interf wrapper->id = interface->id; ast_rwlock_init(&wrapper->wraplock); - /* use the write lock whenever the interface container is modified */ - ast_rwlock_wrlock(&ilock); - ao2_link(interfaces, wrapper); + /* The write lock is already held. */ + ao2_link_nolock(interfaces, wrapper); ast_rwlock_unlock(&ilock); ao2_ref(wrapper, -1); diff --git a/main/format_cap.c b/main/format_cap.c index b632a7b1cf4dfaae2b2ed9f5f9497f466166b389..a3e5131602304e65c434823f76e70e817d1cece4 100644 --- a/main/format_cap.c +++ b/main/format_cap.c @@ -470,7 +470,7 @@ static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast if (!append) { ast_format_cap_remove_all(result); } - it = ao2_iterator_init(cap1->formats, cap2->nolock ? AO2_ITERATOR_DONTLOCK : 0); + it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats,