Bug#574589: can confirm bug on debian squeeze, working patch attached

Alexander Wuerstlein arw at arw.name
Thu Feb 10 17:30:45 UTC 2011


Hello,

I can confirm that this bug also affects pulseaudio on squeeze while not
affecting lenny. When commands are read from stdin (e.g. "echo info |
pacmd") pacmd handles the closing of stdin incorrectly and enters an
endless poll()-loop. The referenced Ubuntu-bug only provides a
workaround by replacing all occurences of "echo <something> | pacmd" by
"pacmd <something>". This is insufficient since it still leaves the
regression, thus breaking other previously working code.

Also, I have ported and tested the upstream patch for the problem.
Please see the attached patch which fixes the problem for me. It's, up
to some small differences, the same as upstream commit
609a005b77b5dc691271f48351bd39e3eecb7dc9.




Ciao,

Alexander Wuerstlein.
-------------- next part --------------
--- pacmd.c.orig	2009-11-23 23:22:41.000000000 +0100
+++ pacmd.c	2011-02-10 16:53:34.000000000 +0100
@@ -45,13 +45,6 @@
 
 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;
@@ -60,7 +53,11 @@
     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];
+
+    struct pollfd pollfd[3];
+    struct pollfd *watch_socket, *watch_stdin, *watch_stdout;
+
+    int stdin_type = 0, stdout_type = 0, fd_type = 0;
 
     setlocale(LC_ALL, "");
     bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
@@ -128,32 +125,53 @@
         ibuf_eof = TRUE;
     }
 
-    pa_zero(pollfd);
-
-    pollfd[WATCH_STDIN].fd = STDIN_FILENO;
-    pollfd[WATCH_STDOUT].fd = STDOUT_FILENO;
-    pollfd[WATCH_SOCKET].fd = fd;
-
     for (;;) {
+        struct pollfd *p;
+
         if (ibuf_eof &&
             obuf_eof &&
             ibuf_length <= 0 &&
             obuf_length <= 0)
             break;
 
-        pollfd[WATCH_STDIN].events = pollfd[WATCH_STDOUT].events = pollfd[WATCH_SOCKET].events = 0;
+        if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
+            shutdown(fd, SHUT_WR);
+            ibuf_closed = TRUE;
+        }
 
-        if (obuf_length > 0)
-            pollfd[WATCH_STDOUT].events |= POLLOUT;
-        else if (!obuf_eof)
-            pollfd[WATCH_SOCKET].events |= POLLIN;
-
-        if (ibuf_length > 0)
-            pollfd[WATCH_SOCKET].events |= POLLOUT;
-        else if (!ibuf_eof)
-            pollfd[WATCH_STDIN].events |= POLLIN;
+        if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
+            shutdown(fd, SHUT_RD);
+            obuf_closed = TRUE;
+        }
+
+        pa_zero(pollfd);
+
+        p = pollfd;
 
-        if (poll(pollfd, N_WATCH, -1) < 0) {
+        if (ibuf_length > 0 || (!obuf_eof && obuf_length <= 0)) {
+            watch_socket = p++;
+            watch_socket->fd = fd;
+            watch_socket->events =
+                (ibuf_length > 0 ? POLLOUT : 0) |
+                (!obuf_eof && obuf_length <= 0 ? POLLIN : 0);
+        } else
+            watch_socket = NULL;
+
+        if (!ibuf_eof && ibuf_length <= 0) {
+            watch_stdin = p++;
+            watch_stdin->fd = STDIN_FILENO;
+            watch_stdin->events = POLLIN;
+        } else
+            watch_stdin = NULL;
+
+        if (obuf_length > 0) {
+            watch_stdout = p++;
+            watch_stdout->fd = STDOUT_FILENO;
+            watch_stdout->events = POLLOUT;
+        } else
+            watch_stdout = NULL;
+
+        if (poll(pollfd, p-pollfd, -1) < 0) {
 
             if (errno == EINTR)
                 continue;
@@ -162,82 +180,80 @@
             goto fail;
         }
 
-        if (pollfd[WATCH_STDIN].revents & POLLIN) {
-            ssize_t r;
-            pa_assert(!ibuf_length);
-
-            if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), NULL)) <= 0) {
-                if (r < 0) {
-                    pa_log(_("read(): %s"), strerror(errno));
-                    goto fail;
+        if (watch_stdin) {
+            if (watch_stdin->revents & POLLIN) {
+                ssize_t r;
+                pa_assert(ibuf_length <= 0);
+
+                if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), &stdin_type)) <= 0) {
+                    if (r < 0) {
+                        pa_log(_("read(): %s"), strerror(errno));
+                        goto fail;
+                    }
+
+                    ibuf_eof = TRUE;
+                } else {
+                    ibuf_length = (size_t) r;
+                    ibuf_index = 0;
                 }
-
+            } else if (watch_stdin->revents & POLLHUP)
                 ibuf_eof = TRUE;
-            } else {
-                ibuf_length = (size_t) r;
-                ibuf_index = 0;
-            }
         }
 
-        if (pollfd[WATCH_SOCKET].revents & POLLIN) {
-            ssize_t r;
-            pa_assert(!obuf_length);
-
-            if ((r = pa_read(fd, obuf, sizeof(obuf), NULL)) <= 0) {
-                if (r < 0) {
-                    pa_log(_("read(): %s"), strerror(errno));
-                    goto fail;
+        if (watch_socket) {
+            if (watch_socket->revents & POLLIN) {
+                ssize_t r;
+                pa_assert(obuf_length <= 0);
+
+                if ((r = pa_read(fd, obuf, sizeof(obuf), &fd_type)) <= 0) {
+                    if (r < 0) {
+                        pa_log(_("read(): %s"), strerror(errno));
+                        goto fail;
+                    }
+
+                    obuf_eof = TRUE;
+                } else {
+                    obuf_length = (size_t) r;
+                    obuf_index = 0;
                 }
-
+            } else if (watch_socket->revents & POLLHUP)
                 obuf_eof = TRUE;
-            } else {
-                obuf_length = (size_t) r;
-                obuf_index = 0;
-            }
         }
 
-        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(STDOUT_FILENO, obuf + obuf_index, obuf_length, NULL)) < 0) {
-                pa_log(_("write(): %s"), strerror(errno));
-                goto fail;
-            }
+        if (watch_stdout) {
+            if (watch_stdout->revents & POLLHUP) {
+                obuf_eof = TRUE;
+                obuf_length = 0;
+            } else if (watch_stdout->revents & POLLOUT) {
+                ssize_t r;
+                pa_assert(obuf_length > 0);
 
-            obuf_length -= (size_t) r;
-            obuf_index += obuf_index;
-        }
+                if ((r = pa_write(STDOUT_FILENO, obuf + obuf_index, obuf_length, &stdout_type)) < 0) {
+                    pa_log(_("write(): %s"), strerror(errno));
+                    goto fail;
+                }
 
-        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);
-
-            if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, NULL)) < 0) {
-                pa_log(_("write(): %s"), strerror(errno));
-                goto fail;
+                obuf_length -= (size_t) r;
+                obuf_index += obuf_index;
             }
-
-            ibuf_length -= (size_t) r;
-            ibuf_index += obuf_index;
         }
 
-        if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
-            pa_close(STDIN_FILENO);
-            shutdown(fd, SHUT_WR);
-            ibuf_closed = TRUE;
-        }
+        if (watch_socket) {
+            if (watch_socket->revents & POLLHUP) {
+                ibuf_eof = TRUE;
+                ibuf_length = 0;
+            } if (watch_socket->revents & POLLOUT) {
+                ssize_t r;
+                pa_assert(ibuf_length > 0);
 
-        if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
-            shutdown(fd, SHUT_RD);
-            pa_close(STDOUT_FILENO);
-            obuf_closed = TRUE;
+                if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, &fd_type)) < 0) {
+                    pa_log(_("write(): %s"), strerror(errno));
+                    goto fail;
+                }
+
+                ibuf_length -= (size_t) r;
+                ibuf_index += obuf_index;
+            }
         }
     }
 


More information about the pkg-pulseaudio-devel mailing list