mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
Fix ao2_callback when both OBJ_MULTIPLE and OBJ_NODATA are passed.
There is an issue which only affects trunk and the new ao2_callback OBJ_MULTIPLE implementation. When both OBJ_MULTIPLE and OBJ_NODATA are passed, only the first object is visited, regardless of what is returned by the specified callback. This causes a problem when we are clearing a container, i.e.: ao2_callback(container, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); Only unlinks the first object. This patch resolves this. (closes issue #16564) Reported by: pj Patches: issue16564_20100111.diff uploaded by seanbright (license 71) Tested by: pj, seanbright Review: https://reviewboard.asterisk.org/r/457/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@239113 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -593,6 +593,8 @@ static int cb_true_data(void *user_data, void *arg, void *data, int flags)
|
||||
return CMP_MATCH;
|
||||
}
|
||||
|
||||
#define USE_CONTAINER(x) (((x) & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE)
|
||||
|
||||
/*!
|
||||
* Browse the container using different stategies accoding the flags.
|
||||
* \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
|
||||
@@ -615,7 +617,7 @@ static void *internal_ao2_callback(struct ao2_container *c,
|
||||
if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
|
||||
return NULL;
|
||||
|
||||
if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
|
||||
if (USE_CONTAINER(flags)) {
|
||||
/* we need to return an ao2_iterator with the results,
|
||||
* as there could be more than one. the iterator will
|
||||
* hold the only reference to a container that has all the
|
||||
@@ -708,7 +710,7 @@ static void *internal_ao2_callback(struct ao2_container *c,
|
||||
/* if we are in OBJ_MULTIPLE mode, link the object into the
|
||||
* container that will hold the results
|
||||
*/
|
||||
if (ret && (multi_container != NULL)) {
|
||||
if (ret && USE_CONTAINER(flags)) {
|
||||
__ao2_link(multi_container, ret);
|
||||
ret = NULL;
|
||||
}
|
||||
@@ -731,9 +733,10 @@ static void *internal_ao2_callback(struct ao2_container *c,
|
||||
ast_free(cur); /* free the link record */
|
||||
}
|
||||
|
||||
if ((match & CMP_STOP) || (multi_container == NULL)) {
|
||||
/* We found the only match we need */
|
||||
i = last; /* force exit from outer loop */
|
||||
if ((match & CMP_STOP) || USE_CONTAINER(flags)) {
|
||||
/* We found our only (or last) match, so force an exit from
|
||||
the outside loop. */
|
||||
i = last;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -750,7 +753,7 @@ static void *internal_ao2_callback(struct ao2_container *c,
|
||||
}
|
||||
}
|
||||
ao2_unlock(c);
|
||||
if (multi_container != NULL) {
|
||||
if (USE_CONTAINER(flags)) {
|
||||
*multi_iterator = ao2_iterator_init(multi_container,
|
||||
AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
|
||||
ao2_ref(multi_container, -1);
|
||||
|
Reference in New Issue
Block a user