2014-05-22 10:33:59

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/5] unit/test-queue: Add /queue/foreach_destroy test

From: Luiz Augusto von Dentz <[email protected]>

This tests queue_destroy from queue_foreach callback.
---
unit/test-queue.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/unit/test-queue.c b/unit/test-queue.c
index 7c6d2ad..55273e3 100644
--- a/unit/test-queue.c
+++ b/unit/test-queue.c
@@ -58,11 +58,32 @@ static void test_basic(void)
queue_destroy(queue, NULL);
}

+static void foreach_destroy(void *data, void *user_data)
+{
+ struct queue *queue = user_data;
+
+ queue_destroy(queue, NULL);
+}
+
+static void test_foreach_destroy(void)
+{
+ struct queue *queue;
+
+ queue = queue_new();
+ g_assert(queue != NULL);
+
+ queue_push_tail(queue, UINT_TO_PTR(1));
+ queue_push_tail(queue, UINT_TO_PTR(2));
+
+ queue_foreach(queue, foreach_destroy, queue);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);

g_test_add_func("/queue/basic", test_basic);
+ g_test_add_func("/queue/foreach_destroy", test_foreach_destroy);

return g_test_run();
}
--
1.9.0



2014-05-22 10:34:03

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 5/5] shared/queue: Make queue_find default do direct match for NULL callback

From: Luiz Augusto von Dentz <[email protected]>

---
src/shared/queue.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/shared/queue.c b/src/shared/queue.c
index b589055..36da5fe 100644
--- a/src/shared/queue.c
+++ b/src/shared/queue.c
@@ -212,7 +212,7 @@ void queue_foreach(struct queue *queue, queue_foreach_func_t function,

function(tmp->data, user_data);

- if (!queue_find(queue, direct_match, entry))
+ if (!queue_find(queue, NULL, entry))
break;
}
queue_unref(queue);
@@ -226,6 +226,9 @@ void *queue_find(struct queue *queue, queue_match_func_t function,
if (!queue || !function)
return NULL;

+ if (!function)
+ function = direct_match;
+
for (entry = queue->head; entry; entry = entry->next)
if (function(entry->data, match_data))
return entry->data;
--
1.9.0


2014-05-22 10:34:02

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 4/5] shared/queue: Fix queue_foreach not detecting queue has changed

From: Luiz Augusto von Dentz <[email protected]>

This fixes queue_foreach crashing if callback calls queue_remove_all.
---
src/shared/queue.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/src/shared/queue.c b/src/shared/queue.c
index c9c0812..b589055 100644
--- a/src/shared/queue.c
+++ b/src/shared/queue.c
@@ -187,6 +187,11 @@ void *queue_peek_tail(struct queue *queue)
return queue->tail->data;
}

+static bool direct_match(const void *a, const void *b)
+{
+ return a == b;
+}
+
void queue_foreach(struct queue *queue, queue_foreach_func_t function,
void *user_data)
{
@@ -206,6 +211,9 @@ void queue_foreach(struct queue *queue, queue_foreach_func_t function,
entry = tmp->next;

function(tmp->data, user_data);
+
+ if (!queue_find(queue, direct_match, entry))
+ break;
}
queue_unref(queue);
}
--
1.9.0


2014-05-22 10:34:01

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 3/5] unit/test-queue: Add /queue/foreach_remove_all test

From: Luiz Augusto von Dentz <[email protected]>

This tests queue_remove_all from queue_foreach callback.
---
unit/test-queue.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/unit/test-queue.c b/unit/test-queue.c
index 55273e3..af7dfd3 100644
--- a/unit/test-queue.c
+++ b/unit/test-queue.c
@@ -78,12 +78,33 @@ static void test_foreach_destroy(void)
queue_foreach(queue, foreach_destroy, queue);
}

+static void foreach_remove_all(void *data, void *user_data)
+{
+ struct queue *queue = user_data;
+
+ queue_remove_all(queue, NULL, NULL, NULL);
+}
+
+static void test_foreach_remove_all(void)
+{
+ struct queue *queue;
+
+ queue = queue_new();
+ g_assert(queue != NULL);
+
+ queue_push_tail(queue, UINT_TO_PTR(1));
+ queue_push_tail(queue, UINT_TO_PTR(2));
+
+ queue_foreach(queue, foreach_remove_all, queue);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);

g_test_add_func("/queue/basic", test_basic);
g_test_add_func("/queue/foreach_destroy", test_foreach_destroy);
+ g_test_add_func("/queue/foreach_remove_all", test_foreach_remove_all);

return g_test_run();
}
--
1.9.0


2014-05-22 10:34:00

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/5] shared/queue: Fix queue_foreach not detecting queue has been destroyed

From: Luiz Augusto von Dentz <[email protected]>

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


2014-06-27 08:53:58

by Stefan Seyfried

[permalink] [raw]
Subject: Re: [PATCH BlueZ 3/5] unit/test-queue: Add /queue/foreach_remove_all test

Hi Luiz,

Am 22.05.2014 12:34, schrieb Luiz Augusto von Dentz:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This tests queue_remove_all from queue_foreach callback.

this test is broken. It always fails.

export MALLOC_CHECK_=3
export MALLOC_PERTURB_=69

seife@susi:/local/seife/src/git-repos/bluez-git> unit/test-queue
/queue/basic: OK
/queue/foreach_destroy: OK
/queue/foreach_remove_all: Segmentation fault

in gdb:

/queue/basic: OK
/queue/foreach_destroy: OK
/queue/foreach_remove_all:
Program received signal SIGSEGV, Segmentation fault.
queue_foreach (queue=0x55555575a140, function=0x555555554b20 <foreach_remove_all>, user_data=0x55555575a140)
at src/shared/queue.c:206
206 entry = tmp->next;
(gdb) bt
#0 queue_foreach (queue=0x55555575a140, function=0x555555554b20 <foreach_remove_all>,
user_data=0x55555575a140) at src/shared/queue.c:206
#1 0x00007ffff7b408f1 in test_case_run (tc=0x55555575a260) at gtestutils.c:2059
#2 g_test_run_suite_internal (suite=suite@entry=0x555555759840, path=path@entry=0x7ffff7b96d5e "")
at gtestutils.c:2120
#3 0x00007ffff7b40ab6 in g_test_run_suite_internal (suite=suite@entry=0x555555759820,
path=path@entry=0x7ffff7b96d5e "") at gtestutils.c:2131
#4 0x00007ffff7b40e0b in g_test_run_suite (suite=0x555555759820) at gtestutils.c:2184
#5 0x00007ffff7b40e41 in g_test_run () at gtestutils.c:1488
#6 0x00005555555549fb in main (argc=1, argv=0x7fffffffdae8) at unit/test-queue.c:109
(gdb) print tmp
$1 = (struct queue_entry *) 0x4545454545454545
(gdb)


I noticed the build failing after trying to update openSUSE
Factory to bluez 5.20 and bisected the problem to this test.

For now I disabled the test in the openSUSE package.

Best regards,

Stefan

> ---
> unit/test-queue.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/unit/test-queue.c b/unit/test-queue.c
> index 55273e3..af7dfd3 100644
> --- a/unit/test-queue.c
> +++ b/unit/test-queue.c
> @@ -78,12 +78,33 @@ static void test_foreach_destroy(void)
> queue_foreach(queue, foreach_destroy, queue);
> }
>
> +static void foreach_remove_all(void *data, void *user_data)
> +{
> + struct queue *queue = user_data;
> +
> + queue_remove_all(queue, NULL, NULL, NULL);
> +}
> +
> +static void test_foreach_remove_all(void)
> +{
> + struct queue *queue;
> +
> + queue = queue_new();
> + g_assert(queue != NULL);
> +
> + queue_push_tail(queue, UINT_TO_PTR(1));
> + queue_push_tail(queue, UINT_TO_PTR(2));
> +
> + queue_foreach(queue, foreach_remove_all, queue);
> +}
> +
> int main(int argc, char *argv[])
> {
> g_test_init(&argc, &argv, NULL);
>
> g_test_add_func("/queue/basic", test_basic);
> g_test_add_func("/queue/foreach_destroy", test_foreach_destroy);
> + g_test_add_func("/queue/foreach_remove_all", test_foreach_remove_all);
>
> return g_test_run();
> }

--
Stefan Seyfried
Linux Consultant & Developer -- GPG Key: 0x731B665B

B1 Systems GmbH
Osterfeldstraße 7 / 85088 Vohburg / http://www.b1-systems.de
GF: Ralph Dehner / Unternehmenssitz: Vohburg / AG: Ingolstadt,HRB 3537