Fix alsa_init() error path.
authorAndre Noll <maan@systemlinux.org>
Sun, 20 Feb 2011 16:01:15 +0000 (17:01 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 20 Feb 2011 19:26:29 +0000 (20:26 +0100)
If alsa_init() fails, alsa_write_post_select() removes the buffer tree
node and sets t->error to a negative value. para_audiod (or para_write)
then calls alsa->close() to deallocate any resources. At this point
wn->private_data is non-NULL while  pad->handle _is_ NULL. The
subsequent call to snd_pcm_nonblock() therefore triggers the assertion

para_audiod: pcm.c:724: snd_pcm_nonblock: Assertion `pcm' failed.

which aborts para_audiod. Fix this bug by freeing the ->private_data
pointer already in alsa_write_post_select() if alsa_init() fails. This
way, ->private_data and pad->handle are either both NULL or both
non-NULL, which meets the expectations of alsa_close().

alsa_write.c

index d649341..ae3bbfb 100644 (file)
@@ -231,10 +231,9 @@ again:
        if (!pad) {
                int32_t val;
 
-               pad = para_calloc(sizeof(*pad));
-               wn->private_data = pad;
                if (bytes == 0) /* no data available */
                        return;
+               pad = para_calloc(sizeof(*pad));
                get_btr_sample_rate(btrn, &val);
                pad->sample_rate = val;
                get_btr_channels(btrn, &val);
@@ -245,8 +244,11 @@ again:
                PARA_INFO_LOG("%d channel(s), %dHz\n", pad->channels,
                        pad->sample_rate);
                ret = alsa_init(pad, wn->conf);
-               if (ret < 0)
+               if (ret < 0) {
+                       free(pad);
                        goto err;
+               }
+               wn->private_data = pad;
                wn->min_iqs = pad->bytes_per_frame;
                goto again;
        }