From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This fixes queue_foreach crashing if it callback call queue_destroy. --- src/shared/queue.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/shared/queue.c b/src/shared/queue.c index ea4ff96..c9c0812 100644 --- a/src/shared/queue.c +++ b/src/shared/queue.c @@ -34,11 +34,30 @@ struct queue_entry { }; struct queue { + int ref_count; struct queue_entry *head; struct queue_entry *tail; unsigned int entries; }; +static struct queue *queue_ref(struct queue *queue) +{ + if (!queue) + return NULL; + + __sync_fetch_and_add(&queue->ref_count, 1); + + return queue; +} + +static void queue_unref(struct queue *queue) +{ + if (__sync_sub_and_fetch(&queue->ref_count, 1)) + return; + + free(queue); +} + struct queue *queue_new(void) { struct queue *queue; @@ -51,7 +70,7 @@ struct queue *queue_new(void) queue->tail = NULL; queue->entries = 0; - return queue; + return queue_ref(queue); } void queue_destroy(struct queue *queue, queue_destroy_func_t destroy) @@ -74,7 +93,7 @@ void queue_destroy(struct queue *queue, queue_destroy_func_t destroy) free(tmp); } - free(queue); + queue_unref(queue); } bool queue_push_tail(struct queue *queue, void *data) @@ -177,14 +196,18 @@ void queue_foreach(struct queue *queue, queue_foreach_func_t function, return; entry = queue->head; + if (!entry) + return; - while (entry) { + queue_ref(queue); + while (entry && queue->ref_count > 1) { struct queue_entry *tmp = entry; entry = tmp->next; function(tmp->data, user_data); } + queue_unref(queue); } void *queue_find(struct queue *queue, queue_match_func_t function, -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html