From 3c9344a1a9de335925b81058b7699fccd187626b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 20 Feb 2015 19:58:24 +0100 Subject: [PATCH] stream_file: open pipes non-blocking Now the player can actually be quit if a pipe was opened, but nobody is writing to it. --- stream/stream_file.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/stream/stream_file.c b/stream/stream_file.c index a78cda1f89..5ce346b706 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -27,6 +27,10 @@ #include #include +#ifndef __MINGW32__ +#include +#endif + #include "osdep/io.h" #include "common/common.h" @@ -57,11 +61,24 @@ struct priv { int fd; bool close; + bool regular; }; static int fill_buffer(stream_t *s, char *buffer, int max_len) { struct priv *p = s->priv; +#ifndef __MINGW32__ + if (!p->regular) { + int c = s->cancel ? mp_cancel_get_fd(s->cancel) : -1; + struct pollfd fds[2] = { + {.fd = p->fd, .events = POLLIN}, + {.fd = c, .events = POLLIN}, + }; + poll(fds, c >= 0 ? 2 : 1, -1); + if (fds[1].revents & POLLIN) + return -1; + } +#endif int r = read(p->fd, buffer, max_len); return (r <= 0) ? -1 : r; } @@ -250,6 +267,8 @@ static int open_f(stream_t *stream) mode_t openmode = S_IRUSR | S_IWUSR; #ifndef __MINGW32__ openmode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + if (!write) + m |= O_NONBLOCK; #endif fd = open(filename, m | O_BINARY, openmode); if (fd < 0) { @@ -258,10 +277,20 @@ static int open_f(stream_t *stream) return STREAM_ERROR; } struct stat st; - if (fstat(fd, &st) == 0 && S_ISDIR(st.st_mode)) { - MP_ERR(stream, "File is a directory: '%s'\n", filename); - close(fd); - return STREAM_ERROR; + if (fstat(fd, &st) == 0) { + if (S_ISDIR(st.st_mode)) { + MP_ERR(stream, "File is a directory: '%s'\n", filename); + close(fd); + return STREAM_ERROR; + } +#ifndef __MINGW32__ + if (S_ISREG(st.st_mode)) { + priv->regular = true; + // O_NONBLOCK has weird semantics on file locks; remove it. + int val = fcntl(fd, F_GETFL) & ~(unsigned)O_NONBLOCK; + fcntl(fd, F_SETFL, val); + } +#endif } priv->fd = fd; priv->close = true;