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