pacmd: port pacmd from select() to poll() so that we notice writer side hangups

This commit is contained in:
Lennart Poettering 2009-08-12 21:42:02 +02:00
parent 286ab2f193
commit 5fcb8a3c08

View file

@ -25,7 +25,7 @@
#include <assert.h> #include <assert.h>
#include <signal.h> #include <signal.h>
#include <sys/select.h> #include <sys/poll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -45,6 +45,13 @@
int main(int argc, char*argv[]) { int main(int argc, char*argv[]) {
enum {
WATCH_STDIN,
WATCH_STDOUT,
WATCH_SOCKET,
N_WATCH
};
pid_t pid ; pid_t pid ;
int fd = -1; int fd = -1;
int ret = 1, i; int ret = 1, i;
@ -53,6 +60,7 @@ int main(int argc, char*argv[]) {
size_t ibuf_index, ibuf_length, obuf_index, obuf_length; size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
char *cli; char *cli;
pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed; pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed;
struct pollfd pollfd[N_WATCH];
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
@ -120,38 +128,45 @@ int main(int argc, char*argv[]) {
ibuf_eof = TRUE; ibuf_eof = TRUE;
} }
for (;;) { pa_zero(pollfd);
fd_set ifds, ofds;
pollfd[WATCH_STDIN].fd = STDIN_FILENO;
pollfd[WATCH_STDOUT].fd = STDOUT_FILENO;
pollfd[WATCH_SOCKET].fd = fd;
for (;;) {
if (ibuf_eof && if (ibuf_eof &&
obuf_eof && obuf_eof &&
ibuf_length <= 0 && ibuf_length <= 0 &&
obuf_length <= 0) obuf_length <= 0)
break; break;
FD_ZERO(&ifds); pollfd[WATCH_STDIN].events = pollfd[WATCH_STDOUT].events = pollfd[WATCH_SOCKET].events = 0;
FD_ZERO(&ofds);
if (obuf_length > 0) if (obuf_length > 0)
FD_SET(1, &ofds); pollfd[WATCH_STDOUT].events |= POLLOUT;
else if (!obuf_eof) else if (!obuf_eof)
FD_SET(fd, &ifds); pollfd[WATCH_SOCKET].events |= POLLIN;
if (ibuf_length > 0) if (ibuf_length > 0)
FD_SET(fd, &ofds); pollfd[WATCH_SOCKET].events |= POLLOUT;
else if (!ibuf_eof) else if (!ibuf_eof)
FD_SET(0, &ifds); pollfd[WATCH_STDIN].events |= POLLIN;
if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { if (poll(pollfd, N_WATCH, -1) < 0) {
pa_log(_("select(): %s"), strerror(errno));
if (errno == EINTR)
continue;
pa_log(_("poll(): %s"), strerror(errno));
goto fail; goto fail;
} }
if (FD_ISSET(0, &ifds)) { if (pollfd[WATCH_STDIN].revents & POLLIN) {
ssize_t r; ssize_t r;
pa_assert(!ibuf_length); pa_assert(!ibuf_length);
if ((r = pa_read(0, ibuf, sizeof(ibuf), NULL)) <= 0) { if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), NULL)) <= 0) {
if (r < 0) { if (r < 0) {
pa_log(_("read(): %s"), strerror(errno)); pa_log(_("read(): %s"), strerror(errno));
goto fail; goto fail;
@ -164,7 +179,7 @@ int main(int argc, char*argv[]) {
} }
} }
if (FD_ISSET(fd, &ifds)) { if (pollfd[WATCH_SOCKET].revents & POLLIN) {
ssize_t r; ssize_t r;
pa_assert(!obuf_length); pa_assert(!obuf_length);
@ -181,21 +196,26 @@ int main(int argc, char*argv[]) {
} }
} }
if (FD_ISSET(1, &ofds)) { if (pollfd[WATCH_STDOUT].revents & POLLHUP) {
obuf_eof = TRUE;
obuf_length = 0;
} else if (pollfd[WATCH_STDOUT].revents & POLLOUT) {
ssize_t r; ssize_t r;
pa_assert(obuf_length); pa_assert(obuf_length);
if ((r = pa_write(1, obuf + obuf_index, obuf_length, NULL)) < 0) { if ((r = pa_write(STDOUT_FILENO, obuf + obuf_index, obuf_length, NULL)) < 0) {
pa_log(_("write(): %s"), strerror(errno)); pa_log(_("write(): %s"), strerror(errno));
goto fail; goto fail;
} }
obuf_length -= (size_t) r; obuf_length -= (size_t) r;
obuf_index += obuf_index; obuf_index += obuf_index;
} }
if (FD_ISSET(fd, &ofds)) { if (pollfd[WATCH_SOCKET].revents & POLLHUP) {
ibuf_eof = TRUE;
ibuf_length = 0;
} if (pollfd[WATCH_SOCKET].revents & POLLOUT) {
ssize_t r; ssize_t r;
pa_assert(ibuf_length); pa_assert(ibuf_length);
@ -209,14 +229,14 @@ int main(int argc, char*argv[]) {
} }
if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) { if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
pa_close(0); pa_close(STDIN_FILENO);
shutdown(fd, SHUT_WR); shutdown(fd, SHUT_WR);
ibuf_closed = TRUE; ibuf_closed = TRUE;
} }
if (obuf_length <= 0 && obuf_eof && !obuf_closed) { if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
shutdown(fd, SHUT_RD); shutdown(fd, SHUT_RD);
pa_close(1); pa_close(STDOUT_FILENO);
obuf_closed = TRUE; obuf_closed = TRUE;
} }
} }