OSDN Git Service

Fix bt_cancel_discovery to not call callback.
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>
Tue, 28 Apr 2009 20:37:32 +0000 (17:37 -0300)
committerJohan Hedberg <johan.hedberg@nokia.com>
Wed, 29 Apr 2009 21:35:41 +0000 (00:35 +0300)
bt_cancel_discovery when disconnecting async and calling the callback
which cause crashes if the user data is free'd in between.

audio/headset.c
common/glib-helper.c
serial/port.c
src/device.c

index 1966a25..78a8f76 100644 (file)
@@ -2081,6 +2081,7 @@ static void path_unregister(void *data)
 
        if (hs->state > HEADSET_STATE_DISCONNECTED) {
                debug("Headset unregistered while device was connected!");
+               bt_cancel_discovery(&dev->src, &dev->dst);
                headset_set_state(dev, HEADSET_STATE_DISCONNECTED);
        }
 
index e892a89..bdee098 100644 (file)
@@ -147,6 +147,7 @@ struct search_context {
        bt_destroy_t            destroy;
        gpointer                user_data;
        uuid_t                  uuid;
+       guint                   io_id;
 };
 
 static GSList *context_list = NULL;
@@ -252,6 +253,7 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user
        int sk, err = 0;
 
        sk = g_io_channel_unix_get_fd(chan);
+       ctxt->io_id = 0;
 
        len = sizeof(err);
        if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
@@ -322,8 +324,9 @@ static int create_search_context(struct search_context **ctxt,
        (*ctxt)->uuid = *uuid;
 
        chan = g_io_channel_unix_new(sdp_get_socket(s));
-       g_io_add_watch(chan, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-                       connect_watch, *ctxt);
+       (*ctxt)->io_id = g_io_add_watch(chan,
+                               G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               connect_watch, *ctxt);
        g_io_channel_unref(chan);
 
        return 0;
@@ -388,7 +391,12 @@ int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
        if (!ctxt->session)
                return -ENOTCONN;
 
-       close(ctxt->session->sock);
+       if (ctxt->io_id)
+               g_source_remove(ctxt->io_id);
+
+       sdp_close(ctxt->session);
+
+       search_context_cleanup(ctxt);
        return 0;
 }
 
index 72025fd..4261075 100644 (file)
@@ -145,7 +145,10 @@ static int port_release(struct serial_port *port)
                        g_io_channel_shutdown(port->io, TRUE, NULL);
                        g_io_channel_unref(port->io);
                        port->io = NULL;
-               }
+               } else
+                       bt_cancel_discovery(&port->device->src,
+                                               &port->device->dst);
+
                return 0;
        }
 
index e999c95..46fe7a0 100644 (file)
@@ -424,9 +424,35 @@ static DBusMessage *set_property(DBusConnection *conn,
        return invalid_args(msg);
 }
 
+static void browse_req_free(struct browse_req *req)
+{
+       struct btd_device *device = req->device;
+
+       device->discov_active = 0;
+
+       if (device->discov_requestor) {
+               g_dbus_remove_watch(req->conn, device->discov_listener);
+               device->discov_listener = 0;
+               g_free(device->discov_requestor);
+               device->discov_requestor = NULL;
+       }
+
+       if (req->msg)
+               dbus_message_unref(req->msg);
+       if (req->conn)
+               dbus_connection_unref(req->conn);
+       g_slist_foreach(req->profiles_added, (GFunc) g_free, NULL);
+       g_slist_free(req->profiles_added);
+       g_slist_free(req->profiles_removed);
+       if (req->records)
+               sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
+       g_free(req);
+}
+
 static void discover_services_req_exit(DBusConnection *conn, void *user_data)
 {
-       struct btd_device *device = user_data;
+       struct browse_req *req = user_data;
+       struct btd_device *device = req->device;
        struct btd_adapter *adapter = device->adapter;
        bdaddr_t src;
 
@@ -435,6 +461,8 @@ static void discover_services_req_exit(DBusConnection *conn, void *user_data)
        debug("DiscoverDevices requestor exited");
 
        bt_cancel_discovery(&src, &device->bdaddr);
+
+       browse_req_free(req);
 }
 
 static DBusMessage *discover_services(DBusConnection *conn,
@@ -1236,31 +1264,6 @@ static void store_profiles(struct btd_device *device)
        g_free(str);
 }
 
-static void browse_req_free(struct browse_req *req)
-{
-       struct btd_device *device = req->device;
-
-       device->discov_active = 0;
-
-       if (device->discov_requestor) {
-               g_dbus_remove_watch(req->conn, device->discov_listener);
-               device->discov_listener = 0;
-               g_free(device->discov_requestor);
-               device->discov_requestor = NULL;
-       }
-
-       if (req->msg)
-               dbus_message_unref(req->msg);
-       if (req->conn)
-               dbus_connection_unref(req->conn);
-       g_slist_foreach(req->profiles_added, (GFunc) g_free, NULL);
-       g_slist_free(req->profiles_added);
-       g_slist_free(req->profiles_removed);
-       if (req->records)
-               sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
-       g_free(req);
-}
-
 static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
 {
        struct browse_req *req = user_data;
@@ -1419,7 +1422,7 @@ int device_browse(struct btd_device *device, DBusConnection *conn,
                device->discov_listener = g_dbus_add_disconnect_watch(conn,
                                                sender,
                                                discover_services_req_exit,
-                                               device, NULL);
+                                               req, NULL);
        }
 
        err = bt_search_service(&src, &device->bdaddr,