[vlc-commits] access_out_file: block SIGPIPE while writing to a pipe

Rémi Denis-Courmont git at videolan.org
Tue May 26 22:28:13 CEST 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue May 26 23:23:07 2015 +0300| [236bacecb9e41f698321dbdce9606b1b4002461b] | committer: Rémi Denis-Courmont

access_out_file: block SIGPIPE while writing to a pipe

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=236bacecb9e41f698321dbdce9606b1b4002461b
---

 modules/access_output/Makefile.am |    1 +
 modules/access_output/file.c      |   58 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/modules/access_output/Makefile.am b/modules/access_output/Makefile.am
index 45e77ae..7c93116 100644
--- a/modules/access_output/Makefile.am
+++ b/modules/access_output/Makefile.am
@@ -2,6 +2,7 @@ access_outdir = $(pluginsdir)/access_output
 
 libaccess_output_dummy_plugin_la_SOURCES = access_output/dummy.c
 libaccess_output_file_plugin_la_SOURCES = access_output/file.c
+libaccess_output_file_plugin_la_LIBADD = $(LIBPTHREAD)
 libaccess_output_http_plugin_la_SOURCES = access_output/http.c
 libaccess_output_udp_plugin_la_SOURCES = access_output/udp.c
 libaccess_output_udp_plugin_la_LIBADD = $(SOCKET_LIBS) $(LIBPTHREAD)
diff --git a/modules/access_output/file.c b/modules/access_output/file.c
index 8a2d94e..87213c9 100644
--- a/modules/access_output/file.c
+++ b/modules/access_output/file.c
@@ -31,6 +31,7 @@
 #endif
 
 #include <assert.h>
+#include <signal.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -103,6 +104,59 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
 }
 
 #ifdef S_ISSOCK
+static ssize_t WritePipe(sout_access_out_t *access, block_t *block)
+{
+    int fd = (intptr_t)access->p_sys;
+    ssize_t total = 0;
+    sigset_t set, oldset;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGPIPE);
+    pthread_sigmask(SIG_BLOCK, &set, &oldset);
+
+    while (block != NULL)
+    {
+        if (block->i_buffer == 0)
+        {
+            block_t *next = block->p_next;
+            block_Release(block);
+            block = next;
+            continue;
+        }
+
+        /* TODO: vectorized I/O with writev() */
+        ssize_t val = write(fd, block->p_buffer, block->i_buffer);
+        if (val < 0)
+        {
+            if (errno == EINTR)
+                continue;
+
+            if (errno == EPIPE)
+            {
+                siginfo_t info;
+                struct timespec ts = { 0, 0 };
+                while (sigtimedwait(&set, &info, &ts) > 0);
+            }
+
+            block_ChainRelease(block);
+            msg_Err(access, "cannot write: %s", vlc_strerror_c(errno));
+            total = -1;
+            break;
+        }
+
+        total += val;
+
+        assert((size_t)val <= block->i_buffer);
+        block->p_buffer += val;
+        block->i_buffer -= val;
+    }
+
+    if (!sigismember(&oldset, SIGPIPE))
+        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
+    return total;
+}
+
 static ssize_t Send(sout_access_out_t *access, block_t *block)
 {
     int fd = (intptr_t)access->p_sys;
@@ -137,6 +191,8 @@ static ssize_t Send(sout_access_out_t *access, block_t *block)
     }
     return total;
 }
+#else
+# define WritePipe Write
 #endif
 
 /*****************************************************************************
@@ -309,7 +365,7 @@ static int Open( vlc_object_t *p_this )
 #endif
     else
     {
-        p_access->pf_write = Write;
+        p_access->pf_write = WritePipe;
         p_access->pf_seek = NoSeek;
     }
     p_access->pf_control = Control;



More information about the vlc-commits mailing list