2013-07-08 15:28:30

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/2] core/service: Rename service_shutdown to service_remove

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

This rename service_shutdown to service_remove to make it more similar to
other internal APIs such as device_remove which only do object
cleanup/free and do not have any disconnect logic.
---
src/device.c | 3 +--
src/service.c | 3 ++-
src/service.h | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/device.c b/src/device.c
index edd377c..afb0cfc 100644
--- a/src/device.c
+++ b/src/device.c
@@ -967,9 +967,8 @@ static void remove_service(gpointer data)
struct btd_service *service = data;
struct btd_device *device = btd_service_get_device(service);

- service_shutdown(service);
device->pending = g_slist_remove(device->pending, service);
- btd_service_unref(service);
+ service_remove(service);
}

static gboolean do_disconnect(gpointer user_data)
diff --git a/src/service.c b/src/service.c
index 83e1c1a..52a8291 100644
--- a/src/service.c
+++ b/src/service.c
@@ -168,12 +168,13 @@ int service_probe(struct btd_service *service)
return err;
}

-void service_shutdown(struct btd_service *service)
+void service_remove(struct btd_service *service)
{
change_state(service, BTD_SERVICE_STATE_UNAVAILABLE, 0);
service->profile->device_remove(service);
service->device = NULL;
service->profile = NULL;
+ btd_service_unref(service);
}

int btd_service_connect(struct btd_service *service)
diff --git a/src/service.h b/src/service.h
index 6ee8f17..5230115 100644
--- a/src/service.h
+++ b/src/service.h
@@ -46,7 +46,7 @@ struct btd_service *service_create(struct btd_device *device,
struct btd_profile *profile);

int service_probe(struct btd_service *service);
-void service_shutdown(struct btd_service *service);
+void service_remove(struct btd_service *service);

/* Connection control API */
int btd_service_connect(struct btd_service *service);
--
1.8.1.4



2013-07-08 17:22:10

by Mikel Astiz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 2/2] core/device: Fix crash while freeing services list

Hi Luiz,

On Mon, Jul 8, 2013 at 5:28 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> btd_service do alter its state on service_remove which can cause
> plugins to attempt to access services list which may have freed some
> services already.
>
> To fix this the code now updates the list in place so the services are
> first removed from services list before calling service_remove.
> ---
> src/device.c | 20 +++++++++++---------
> 1 file changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/src/device.c b/src/device.c
> index afb0cfc..5a1f9c1 100644
> --- a/src/device.c
> +++ b/src/device.c
> @@ -993,8 +993,12 @@ int device_block(struct btd_device *device, gboolean update_only)
> if (device->connected)
> do_disconnect(device);
>
> - g_slist_free_full(device->services, remove_service);
> - device->services = NULL;
> + while (device->services != NULL) {
> + struct btd_service *service = device->services->data;
> +
> + device->services = g_slist_remove(device->services, service);
> + service_remove(service);
> + }
>
> if (!update_only)
> err = btd_adapter_block_address(device->adapter,
> @@ -2361,7 +2365,6 @@ static void device_remove_stored(struct btd_device *device)
>
> void device_remove(struct btd_device *device, gboolean remove_stored)
> {
> -
> DBG("Removing device %s", device->path);
>
> if (device->bonding) {
> @@ -2378,10 +2381,12 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
> if (device->browse)
> browse_request_cancel(device->browse);
>
> - g_slist_foreach(device->services, dev_disconn_service, NULL);

Wouldn't it be better to split this change to a separate patch? I
believe it could be subject to backport or revert.

> + while (device->services != NULL) {
> + struct btd_service *service = device->services->data;
>
> - g_slist_free(device->pending);
> - device->pending = NULL;

Why are the two lines above removed?

> + device->services = g_slist_remove(device->services, service);
> + service_remove(service);
> + }
>
> if (device->connected)
> do_disconnect(device);
> @@ -2397,9 +2402,6 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
> if (remove_stored)
> device_remove_stored(device);
>
> - g_slist_free_full(device->services, remove_service);
> - device->services = NULL;
> -
> btd_device_unref(device);
> }
>
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

Cheers,
Mikel

2013-07-08 17:15:50

by Mikel Astiz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/2] core/service: Rename service_shutdown to service_remove

Hi Luiz,

On Mon, Jul 8, 2013 at 5:28 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This rename service_shutdown to service_remove to make it more similar to
> other internal APIs such as device_remove which only do object
> cleanup/free and do not have any disconnect logic.

I personally don't like hiding unrefs in such a way but it's indeed
more consistent with device_remove() so if this is the convention to
be adopted, ack from my side.

Note however that adapter_remove() doesn't automatically call
btd_adapter_unref() so in this case it would need to be updated too.

Cheers,
Mikel

> ---
> src/device.c | 3 +--
> src/service.c | 3 ++-
> src/service.h | 2 +-
> 3 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/src/device.c b/src/device.c
> index edd377c..afb0cfc 100644
> --- a/src/device.c
> +++ b/src/device.c
> @@ -967,9 +967,8 @@ static void remove_service(gpointer data)
> struct btd_service *service = data;
> struct btd_device *device = btd_service_get_device(service);
>
> - service_shutdown(service);
> device->pending = g_slist_remove(device->pending, service);
> - btd_service_unref(service);
> + service_remove(service);
> }
>
> static gboolean do_disconnect(gpointer user_data)
> diff --git a/src/service.c b/src/service.c
> index 83e1c1a..52a8291 100644
> --- a/src/service.c
> +++ b/src/service.c
> @@ -168,12 +168,13 @@ int service_probe(struct btd_service *service)
> return err;
> }
>
> -void service_shutdown(struct btd_service *service)
> +void service_remove(struct btd_service *service)
> {
> change_state(service, BTD_SERVICE_STATE_UNAVAILABLE, 0);
> service->profile->device_remove(service);
> service->device = NULL;
> service->profile = NULL;
> + btd_service_unref(service);
> }
>
> int btd_service_connect(struct btd_service *service)
> diff --git a/src/service.h b/src/service.h
> index 6ee8f17..5230115 100644
> --- a/src/service.h
> +++ b/src/service.h
> @@ -46,7 +46,7 @@ struct btd_service *service_create(struct btd_device *device,
> struct btd_profile *profile);
>
> int service_probe(struct btd_service *service);
> -void service_shutdown(struct btd_service *service);
> +void service_remove(struct btd_service *service);
>
> /* Connection control API */
> int btd_service_connect(struct btd_service *service);
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2013-07-08 15:28:31

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/2] core/device: Fix crash while freeing services list

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

btd_service do alter its state on service_remove which can cause
plugins to attempt to access services list which may have freed some
services already.

To fix this the code now updates the list in place so the services are
first removed from services list before calling service_remove.
---
src/device.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/device.c b/src/device.c
index afb0cfc..5a1f9c1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -993,8 +993,12 @@ int device_block(struct btd_device *device, gboolean update_only)
if (device->connected)
do_disconnect(device);

- g_slist_free_full(device->services, remove_service);
- device->services = NULL;
+ while (device->services != NULL) {
+ struct btd_service *service = device->services->data;
+
+ device->services = g_slist_remove(device->services, service);
+ service_remove(service);
+ }

if (!update_only)
err = btd_adapter_block_address(device->adapter,
@@ -2361,7 +2365,6 @@ static void device_remove_stored(struct btd_device *device)

void device_remove(struct btd_device *device, gboolean remove_stored)
{
-
DBG("Removing device %s", device->path);

if (device->bonding) {
@@ -2378,10 +2381,12 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
if (device->browse)
browse_request_cancel(device->browse);

- g_slist_foreach(device->services, dev_disconn_service, NULL);
+ while (device->services != NULL) {
+ struct btd_service *service = device->services->data;

- g_slist_free(device->pending);
- device->pending = NULL;
+ device->services = g_slist_remove(device->services, service);
+ service_remove(service);
+ }

if (device->connected)
do_disconnect(device);
@@ -2397,9 +2402,6 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
if (remove_stored)
device_remove_stored(device);

- g_slist_free_full(device->services, remove_service);
- device->services = NULL;
-
btd_device_unref(device);
}

--
1.8.1.4