diff options
author | Arun Raghavan <arun.raghavan@collabora.co.uk> | 2011-10-04 10:29:03 +0530 |
---|---|---|
committer | Arun Raghavan <arun.raghavan@collabora.co.uk> | 2011-10-08 15:16:59 +0530 |
commit | 867170afa78198d265bfb587128921134daf3756 (patch) | |
tree | 0c45022450e782fac2b0def1b3386ca816dd6b95 | |
parent | 4e5943b6ba8b8f6bc45da24bf81d0828d990da20 (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.c | 30 |
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) { |