vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Wed May 13 19:31:53 2015 +0300| [d89c4195077ae0623e39b3c41121ecd9b20d0d9e] | committer: Rémi Denis-Courmont
src: add vlc_write() and vlc_writev() helpers against SIGPIPE We would rather not terminate the whole VLC process in case of a broken pipe or remotely closed TCP connection. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d89c4195077ae0623e39b3c41121ecd9b20d0d9e --- include/vlc_fs.h | 4 ++++ src/libvlccore.sym | 2 ++ src/posix/filesystem.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/win32/filesystem.c | 10 +++++++++ 4 files changed, 71 insertions(+) diff --git a/include/vlc_fs.h b/include/vlc_fs.h index 4786a2e..83d892e 100644 --- a/include/vlc_fs.h +++ b/include/vlc_fs.h @@ -37,6 +37,7 @@ * dirent structure pointers to its callbacks. * - vlc_accept() takes an extra boolean for nonblocking mode (compare with * the flags parameter in POSIX.next accept4()). + * - Writing functions do not emit a SIGPIPE signal in case of broken pipe. */ #include <sys/types.h> @@ -107,6 +108,7 @@ static inline void vlc_rewinddir( DIR *dir ) #endif struct stat; +struct iovec; VLC_API int vlc_stat( const char *filename, struct stat *buf ); VLC_API int vlc_lstat( const char *filename, struct stat *buf ); @@ -115,4 +117,6 @@ VLC_API int vlc_mkstemp( char * ); VLC_API int vlc_dup( int ); VLC_API int vlc_pipe( int[2] ); +VLC_API ssize_t vlc_write( int, const void *, size_t ); +VLC_API ssize_t vlc_writev( int, const struct iovec *, int ); #endif diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 86a3a82..1ae7c98 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -455,6 +455,8 @@ vlc_rename vlc_getcwd vlc_dup vlc_pipe +vlc_write +vlc_writev vlc_socket vlc_accept utf8_vfprintf diff --git a/src/posix/filesystem.c b/src/posix/filesystem.c index 79856e3..2cd6d1b 100644 --- a/src/posix/filesystem.c +++ b/src/posix/filesystem.c @@ -30,6 +30,7 @@ #include <stdio.h> #include <limits.h> /* NAME_MAX */ #include <errno.h> +#include <signal.h> #include <sys/types.h> #include <unistd.h> @@ -271,6 +272,60 @@ int vlc_pipe (int fds[2]) return 0; } +/** + * Writes data to a file descriptor. Unlike write(), if EPIPE error occurs, + * this function does not generate a SIGPIPE signal. + * @note If the file descriptor is known to be neither a pipe/FIFO nor a + * connection-oriented socket, the normal write() should be used. + */ +ssize_t vlc_write(int fd, const void *buf, size_t len) +{ + struct iovec iov = { .iov_base = (void *)buf, .iov_len = len }; + + return vlc_writev(fd, &iov, 1); +} + +/** + * Writes data from an iovec structure to a file descriptor. Unlike writev(), + * if EPIPE error occurs, this function does not generate a SIGPIPE signal. + */ +ssize_t vlc_writev(int fd, const struct iovec *iov, int count) +{ + sigset_t set, oset; + + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &set, &oset); + + ssize_t val = writev(fd, iov, count); + if (val < 0 && errno == EPIPE) + { +#if (_POSIX_REALTIME_SIGNALS > 0) + siginfo_t info; + struct timespec ts = { 0, 0 }; + + while (sigtimedwait(&set, &info, &ts) >= 0 || errno != EAGAIN); +#else + for (;;) + { + sigset_t s; + int num; + + sigpending(&s); + if (!sigismember(&s, SIGPIPE)) + break; + + sigwait(&set, &num); + assert(num == SIGPIPE); + } +#endif + } + + if (!sigismember(&oset, SIGPIPE)) /* Restore the signal mask if changed */ + pthread_sigmask(SIG_SETMASK, &oset, NULL); + return val; +} + #include <vlc_network.h> /** diff --git a/src/win32/filesystem.c b/src/win32/filesystem.c index 045ad99..cf722ab 100644 --- a/src/win32/filesystem.c +++ b/src/win32/filesystem.c @@ -284,6 +284,16 @@ int vlc_pipe (int fds[2]) #endif } +ssize_t vlc_write(int fd, const void *buf, size_t len) +{ + return write(fd, buf, len); +} + +ssize_t vlc_writev(int fd, const struct iovec *iov, int count) +{ + vlc_assert_unreachable(); +} + #include <vlc_network.h> int vlc_socket (int pf, int type, int proto, bool nonblock) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
