commit b02dadd38071fc5f6fec5241c805077e7a5b818d from: Omar Polo date: Sat May 13 15:09:34 2023 UTC cache audio_nfds() ALSA' snd_pcm_poll_descriptors_count() can fail with -EPIPE after an underrun (e.g. after a pause), so we can't call it directly like this. It's also a bit sloppy to always call audio_nfds(), so instead save the (initial) value returned and pass it to the various functions. Issue reported and fix tested by phoebos (ben [at] bvnf [dot] space), thank you! commit - 8b3efdb322551aaf432334c16a23f52789c22989 commit + b02dadd38071fc5f6fec5241c805077e7a5b818d blob - 9127045e119cbe11c5ceedf4292c911ad6371228 blob + b6bba1c01bc22266594c48a8df59d27e7d75f905 --- amused.h +++ amused.h @@ -160,10 +160,10 @@ void main_seek(struct player_seek *); /* audio_*.c */ int audio_open(void (*)(void *, int)); int audio_setup(unsigned int, unsigned int, unsigned int, - struct pollfd *); + struct pollfd *, int); int audio_nfds(void); -int audio_pollfd(struct pollfd *, int); -int audio_revents(struct pollfd *); +int audio_pollfd(struct pollfd *, int, int); +int audio_revents(struct pollfd *, int); size_t audio_write(const void *, size_t); int audio_flush(void); int audio_stop(void); blob - 07f43795676ea21645ad6ae56597c54673a035e1 blob + 656fb1fd2fba1ba957d7f2e32a75e526b31502fb --- audio_alsa.c +++ audio_alsa.c @@ -46,7 +46,7 @@ audio_open(void (*cb)(void *, int)) int audio_setup(unsigned int bits, unsigned int rate, unsigned int channels, - struct pollfd *pfds) + struct pollfd *pfds, int nfds) { int err; snd_pcm_format_t fmt; @@ -93,19 +93,18 @@ audio_nfds(void) } int -audio_pollfd(struct pollfd *pfds, int events) +audio_pollfd(struct pollfd *pfds, int nfds, int events) { - return snd_pcm_poll_descriptors(pcm, pfds, audio_nfds()); + return snd_pcm_poll_descriptors(pcm, pfds, nfds); } int -audio_revents(struct pollfd *pfds) +audio_revents(struct pollfd *pfds, int nfds) { int err; unsigned short revents; - err = snd_pcm_poll_descriptors_revents(pcm, pfds, audio_nfds(), - &revents); + err = snd_pcm_poll_descriptors_revents(pcm, pfds, nfds, &revents); if (err < 0) { log_warnx("snd revents failure: %s", snd_strerror(err)); return 0; blob - 3a44d164a81a7d7317f6284e0b8c84aad10e3e30 blob + 0661a8964490d8814fcdbcc523c7df108198a4e1 --- audio_sndio.c +++ audio_sndio.c @@ -41,9 +41,9 @@ audio_open(void (*onmove_cb)(void *, int)) int audio_setup(unsigned int bits, unsigned int rate, unsigned int channels, - struct pollfd *pfds) + struct pollfd *pfds, int nfds) { - int nfds, fpct; + int fpct; fpct = (rate * 5) / 100; @@ -67,7 +67,7 @@ audio_setup(unsigned int bits, unsigned int rate, unsi par.pchan = channels; if (!sio_setpar(hdl, &par)) { if (errno == EAGAIN) { - nfds = sio_pollfd(hdl, pfds, POLLOUT); + sio_pollfd(hdl, pfds, POLLOUT); if (poll(pfds, nfds, INFTIM) == -1) fatal("poll"); goto again; @@ -104,13 +104,13 @@ audio_nfds(void) } int -audio_pollfd(struct pollfd *pfds, int events) +audio_pollfd(struct pollfd *pfds, int nfds, int events) { return sio_pollfd(hdl, pfds, events); } int -audio_revents(struct pollfd *pfds) +audio_revents(struct pollfd *pfds, int nfds) { return sio_revents(hdl, pfds); } blob - 0ed93412e48712f7bbcc9d065b04ecdb891ba734 blob + 8201dc2ee66cb298413f0d27ea16550637bdd069 --- player.c +++ player.c @@ -34,6 +34,7 @@ #include "xmalloc.h" struct pollfd *player_pfds; +int player_nfds; static struct imsgbuf *ibuf; static int nextfd = -1; @@ -56,7 +57,7 @@ player_setup(unsigned int bits, unsigned int rate, uns bits, rate, channels); current_rate = rate; - return audio_setup(bits, rate, channels, player_pfds + 1); + return audio_setup(bits, rate, channels, player_pfds + 1, player_nfds); } void @@ -253,12 +254,12 @@ int play(const void *buf, size_t len, int64_t *s) { size_t w; - int nfds, revents, r, wait; + int revents, r, wait; *s = -1; while (len != 0) { - nfds = audio_pollfd(player_pfds + 1, POLLOUT); - r = poll(player_pfds, nfds + 1, INFTIM); + audio_pollfd(player_pfds + 1, player_nfds, POLLOUT); + r = poll(player_pfds, player_nfds + 1, INFTIM); if (r == -1) fatal("poll"); @@ -268,7 +269,7 @@ play(const void *buf, size_t len, int64_t *s) return 0; } - revents = audio_revents(player_pfds + 1); + revents = audio_revents(player_pfds + 1, player_nfds); if (revents & POLLHUP) { if (errno == EAGAIN) continue; @@ -307,8 +308,12 @@ player(int debug, int verbose) if (audio_open(player_onmove) == -1) fatal("audio_open"); + if ((player_nfds = audio_nfds()) <= 0) + fatal("audio_nfds: invalid number of file descriptors: %d", + player_nfds); + /* allocate one extra for imsg */ - player_pfds = calloc(audio_nfds() + 1, sizeof(*player_pfds)); + player_pfds = calloc(player_nfds + 1, sizeof(*player_pfds)); if (player_pfds == NULL) fatal("calloc");