summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Raghavan <arun.raghavan@collabora.co.uk>2011-10-04 10:29:03 +0530
committerArun Raghavan <arun.raghavan@collabora.co.uk>2011-10-08 15:16:59 +0530
commit867170afa78198d265bfb587128921134daf3756 (patch)
tree0c45022450e782fac2b0def1b3386ca816dd6b95
parent4e5943b6ba8b8f6bc45da24bf81d0828d990da20 (diff)
alsa: Better error handling in mixer rtpoll callback
This improves the error handling in the mixer rtpoll callback. It avoids a crash if an error occurs (the rtpoll_item is freed but still referenced), and specifically makes sure we don't continue trying to poll the device if the card is disconnected.
-rw-r--r--src/modules/alsa/alsa-mixer.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index ec69efcb..ebb3b0f1 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -271,7 +271,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
struct pollfd *p;
unsigned n_fds;
unsigned short revents = 0;
- int err;
+ int err, ret = 0;
pd = pa_rtpoll_item_get_userdata(i);
pa_assert_fp(pd);
@@ -281,17 +281,33 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
if ((err = snd_mixer_poll_descriptors_revents(pd->mixer, p, n_fds, &revents)) < 0) {
pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err));
- pa_rtpoll_item_free(i);
- return -1;
+ ret = -1;
+ goto fail;
}
if (revents) {
- snd_mixer_handle_events(pd->mixer);
- pa_rtpoll_item_free(i);
- pa_alsa_set_mixer_rtpoll(pd, pd->mixer, pd->rtpoll);
+ err = snd_mixer_handle_events(pd->mixer);
+
+ if (PA_UNLIKELY(err == -ENODEV)) {
+ /* The card has been disconnected, stop polling */
+ goto fail;
+ } else {
+ /* Success, or at least an error we're likely to recover from */
+ pa_rtpoll_item_free(i);
+ pa_alsa_set_mixer_rtpoll(pd, pd->mixer, pd->rtpoll);
+ }
}
- return 0;
+ return ret;
+
+fail:
+ pa_rtpoll_item_free(i);
+
+ pd->poll_item = NULL;
+ pd->rtpoll = NULL;
+ pd->mixer = NULL;
+
+ return ret;
}
int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp) {