[pulseaudio-discuss] [PATCH 07/30] card: Use pa_card_free() in pa_card_new() on failure

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Thu Jan 16 07:02:33 PST 2014


This makes it easier to ensure that resources are not leaked when new
failure conditions are added to pa_card_new() (this patch adds one
such condition: if the card has no profiles, pa_card_new() will fail).
---
 src/pulsecore/card.c | 68 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 29 deletions(-)

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index 3de2787..b780c5b 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -191,8 +191,7 @@ void pa_card_new_data_done(pa_card_new_data *data) {
 }
 
 pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
-    pa_card *c;
-    const char *name;
+    pa_card *c = NULL;
     void *state;
     pa_card_profile *profile;
     pa_device_port *port;
@@ -203,23 +202,21 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
     pa_assert(data->profiles);
     pa_assert(!pa_hashmap_isempty(data->profiles));
 
-    c = pa_xnew(pa_card, 1);
+    c = pa_xnew0(pa_card, 1);
+    c->core = core;
+    pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0);
 
-    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_CARD, c, data->namereg_fail))) {
-        pa_xfree(c);
-        return NULL;
+    c->name = pa_xstrdup(pa_namereg_register(core, data->name, PA_NAMEREG_CARD, c, data->namereg_fail));
+    if (!(c->name)) {
+        pa_log("Failed to register card name '%s'.", data->name);
+        goto fail;
     }
 
-    pa_card_new_data_set_name(data, name);
+    pa_card_new_data_set_name(data, c->name);
 
-    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data) < 0) {
-        pa_xfree(c);
-        pa_namereg_unregister(core, name);
-        return NULL;
-    }
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data) < 0)
+        goto fail;
 
-    c->core = core;
-    c->name = pa_xstrdup(data->name);
     c->proplist = pa_proplist_copy(data->proplist);
     c->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     c->module = data->module;
@@ -242,9 +239,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
     PA_HASHMAP_FOREACH(port, c->ports, state)
         port->card = c;
 
-    c->active_profile = NULL;
     c->recreate_devices_on_profile_switch = data->recreate_devices_on_profile_switch;
-    c->save_profile = false;
 
     if (data->active_profile)
         if ((c->active_profile = pa_hashmap_get(c->profiles, data->active_profile)))
@@ -256,20 +251,26 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
                 c->active_profile = profile;
     }
 
-    c->userdata = NULL;
-    c->set_profile = NULL;
+    if (!c->active_profile) {
+        pa_log("No profiles in card %s.", c->name);
+        goto fail;
+    }
 
     pa_device_init_description(c->proplist);
     pa_device_init_icon(c->proplist, true);
     pa_device_init_intended_roles(c->proplist);
 
-    pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0);
-
     pa_log_info("Created %u \"%s\"", c->index, c->name);
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, c->index);
 
     pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_PUT], c);
     return c;
+
+fail:
+    if (c)
+        pa_card_free(c);
+
+    return NULL;
 }
 
 void pa_card_free(pa_card *c) {
@@ -282,28 +283,37 @@ void pa_card_free(pa_card *c) {
 
     pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], c);
 
-    pa_namereg_unregister(core, c->name);
+    if (c->name)
+        pa_namereg_unregister(core, c->name);
 
-    pa_idxset_remove_by_data(c->core->cards, c, NULL);
+    pa_idxset_remove_by_data(core->cards, c, NULL);
 
-    pa_log_info("Freed %u \"%s\"", c->index, c->name);
+    pa_log_info("Freed %u \"%s\"", c->index, pa_strempty(c->name));
 
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
 
-    pa_assert(pa_idxset_isempty(c->sinks));
-    pa_idxset_free(c->sinks, NULL);
-    pa_assert(pa_idxset_isempty(c->sources));
-    pa_idxset_free(c->sources, NULL);
+    if (c->sinks) {
+        pa_assert(pa_idxset_isempty(c->sinks));
+        pa_idxset_free(c->sinks, NULL);
+    }
+
+    if (c->sources) {
+        pa_assert(pa_idxset_isempty(c->sources));
+        pa_idxset_free(c->sources, NULL);
+    }
 
     if (c->device_prototypes)
         pa_hashmap_free(c->device_prototypes);
 
-    pa_hashmap_free(c->ports);
+    if (c->ports)
+        pa_hashmap_free(c->ports);
 
     if (c->profiles)
         pa_hashmap_free(c->profiles);
 
-    pa_proplist_free(c->proplist);
+    if (c->proplist)
+        pa_proplist_free(c->proplist);
+
     pa_xfree(c->driver);
     pa_xfree(c->name);
     pa_xfree(c);
-- 
1.8.3.1



More information about the pulseaudio-discuss mailing list