OSDN Git Service

Fix a few more ref-leaks with AVDTP failures and unix socket clients
authorJohan Hedberg <johan.hedberg@nokia.com>
Thu, 3 Sep 2009 21:45:52 +0000 (00:45 +0300)
committerJaikumar Ganesh <jaikumar@google.com>
Tue, 29 Sep 2009 00:48:12 +0000 (17:48 -0700)
If any of the IPC messages cause us to create a brand new AVDTP session
and then there's failure caused by disconnection, we have to unref the
session since there will not be a unix.c callback to do it when avdtp.c
wants to clean up in the next mainloop iteration.

audio/unix.c

index 1bc0797..b04cc59 100644 (file)
@@ -884,14 +884,17 @@ static void start_open(struct audio_device *dev, struct unix_client *client)
        struct a2dp_data *a2dp;
        struct headset_data *hs;
        struct avdtp_remote_sep *rsep;
+       gboolean unref_avdtp_on_fail = FALSE;
 
        switch (client->type) {
        case TYPE_SINK:
        case TYPE_SOURCE:
                a2dp = &client->d.a2dp;
 
-               if (!a2dp->session)
+               if (!a2dp->session) {
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
+                       unref_avdtp_on_fail = TRUE;
+               }
 
                if (!a2dp->session) {
                        error("Unable to get a session");
@@ -952,6 +955,10 @@ static void start_open(struct audio_device *dev, struct unix_client *client)
        return;
 
 failed:
+       if (unref_avdtp_on_fail && a2dp->session) {
+               avdtp_unref(a2dp->session);
+               a2dp->session = NULL;
+       }
        unix_ipc_error(client, BT_OPEN, EINVAL);
 }
 
@@ -1027,14 +1034,17 @@ static void start_resume(struct audio_device *dev, struct unix_client *client)
        struct a2dp_data *a2dp;
        struct headset_data *hs;
        unsigned int id;
+       gboolean unref_avdtp_on_fail = FALSE;
 
        switch (client->type) {
        case TYPE_SINK:
        case TYPE_SOURCE:
                a2dp = &client->d.a2dp;
 
-               if (!a2dp->session)
+               if (!a2dp->session) {
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
+                       unref_avdtp_on_fail = TRUE;
+               }
 
                if (!a2dp->session) {
                        error("Unable to get a session");
@@ -1088,6 +1098,10 @@ static void start_resume(struct audio_device *dev, struct unix_client *client)
        return;
 
 failed:
+       if (unref_avdtp_on_fail && a2dp->session) {
+               avdtp_unref(a2dp->session);
+               a2dp->session = NULL;
+       }
        unix_ipc_error(client, BT_START_STREAM, EIO);
 }
 
@@ -1096,14 +1110,17 @@ static void start_suspend(struct audio_device *dev, struct unix_client *client)
        struct a2dp_data *a2dp;
        struct headset_data *hs;
        unsigned int id;
+       gboolean unref_avdtp_on_fail = FALSE;
 
        switch (client->type) {
        case TYPE_SINK:
        case TYPE_SOURCE:
                a2dp = &client->d.a2dp;
 
-               if (!a2dp->session)
+               if (!a2dp->session) {
                        a2dp->session = avdtp_get(&dev->src, &dev->dst);
+                       unref_avdtp_on_fail = TRUE;
+               }
 
                if (!a2dp->session) {
                        error("Unable to get a session");
@@ -1153,6 +1170,10 @@ static void start_suspend(struct audio_device *dev, struct unix_client *client)
        return;
 
 failed:
+       if (unref_avdtp_on_fail && a2dp->session) {
+               avdtp_unref(a2dp->session);
+               a2dp->session = NULL;
+       }
        unix_ipc_error(client, BT_STOP_STREAM, EIO);
 }