summaryrefslogtreecommitdiffstats
path: root/input/pipe-win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'input/pipe-win32.c')
-rw-r--r--input/pipe-win32.c121
1 files changed, 65 insertions, 56 deletions
diff --git a/input/pipe-win32.c b/input/pipe-win32.c
index 4077ea84ee..3d47fb66c1 100644
--- a/input/pipe-win32.c
+++ b/input/pipe-win32.c
@@ -1,98 +1,107 @@
-#include <pthread.h>
-#include <stdio.h>
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include <windows.h>
#include <io.h>
-#include <stdint.h>
-#include <waio/waio.h>
-
#include "common/msg.h"
+#include "osdep/atomics.h"
#include "osdep/io.h"
#include "input.h"
+struct priv {
+ atomic_bool cancel_requested;
+ int fd;
+ bool close_fd;
+ HANDLE file;
+ HANDLE thread;
+};
+
static void request_cancel(struct mp_input_src *src)
{
- HANDLE terminate = src->priv;
+ struct priv *p = src->priv;
MP_VERBOSE(src, "Exiting...\n");
- SetEvent(terminate);
+ atomic_store(&p->cancel_requested, true);
+
+ // The thread might not be peforming I/O at the exact moment when
+ // CancelIoEx is called, so call it in a loop until it succeeds or the
+ // thread exits
+ do {
+ if (CancelIoEx(p->file, NULL))
+ break;
+ } while (WaitForSingleObject(p->thread, 1) != WAIT_OBJECT_0);
}
static void uninit(struct mp_input_src *src)
{
- HANDLE terminate = src->priv;
+ struct priv *p = src->priv;
+
+ CloseHandle(p->thread);
+ if (p->close_fd)
+ close(p->fd);
- CloseHandle(terminate);
MP_VERBOSE(src, "Exited.\n");
}
static void read_pipe_thread(struct mp_input_src *src, void *param)
{
char *filename = talloc_strdup(src, param);
+ struct priv *p = talloc_zero(src, struct priv);
- struct waio_cx_interface *waio = NULL;
- int mode = O_RDONLY;
- int fd = -1;
- bool close_fd = true;
+ p->fd = -1;
+ p->close_fd = true;
if (strcmp(filename, "/dev/stdin") == 0) { // for symmetry with unix
- fd = STDIN_FILENO;
- close_fd = false;
+ p->fd = STDIN_FILENO;
+ p->close_fd = false;
}
- if (fd < 0)
- fd = open(filename, mode);
- if (fd < 0) {
+ if (p->fd < 0)
+ p->fd = open(filename, O_RDONLY);
+ if (p->fd < 0) {
MP_ERR(src, "Can't open %s.\n", filename);
- goto done;
+ return;
}
- // If we're reading from stdin, unset it. All I/O on synchronous handles is
- // serialized, so stupid DLLs that call GetFileType on stdin can hang the
- // process if they do it while we're reading from it. At least, the
- // VirtualBox OpenGL ICD is affected by this, but only on Windows XP.
- // GetFileType works differently in later versions of Windows. See:
- // https://support.microsoft.com/kb/2009703
- // http://blogs.msdn.com/b/oldnewthing/archive/2011/12/02/10243553.aspx
- if ((void*)_get_osfhandle(fd) == GetStdHandle(STD_INPUT_HANDLE))
- SetStdHandle(STD_INPUT_HANDLE, NULL);
-
- waio = waio_alloc((void *)_get_osfhandle(fd), 0, NULL, NULL);
- if (!waio) {
- MP_ERR(src, "Can't initialize win32 file reader.\n");
- goto done;
+ p->file = (HANDLE)_get_osfhandle(p->fd);
+ if (!p->file || p->file == INVALID_HANDLE_VALUE) {
+ MP_ERR(src, "Can't open %s.\n", filename);
+ return;
}
- HANDLE terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!terminate)
- goto done;
+ atomic_store(&p->cancel_requested, false);
+ if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+ GetCurrentProcess(), &p->thread, SYNCHRONIZE, FALSE, 0))
+ return;
- src->priv = terminate;
+ src->priv = p;
src->cancel = request_cancel;
src->uninit = uninit;
mp_input_src_init_done(src);
- char buffer[128];
- struct waio_aiocb cb = {
- .aio_buf = buffer,
- .aio_nbytes = sizeof(buffer),
- .hsignal = terminate,
- };
- while (1) {
- if (waio_read(waio, &cb)) {
- MP_ERR(src, "Read operation failed.\n");
+ char buffer[4096];
+ while (!atomic_load(&p->cancel_requested)) {
+ DWORD r;
+ if (!ReadFile(p->file, buffer, 4096, &r, NULL)) {
+ if (GetLastError() != ERROR_OPERATION_ABORTED)
+ MP_ERR(src, "Read operation failed.\n");
break;
}
- if (waio_suspend(waio, (const struct waio_aiocb *[]){&cb}, 1, NULL))
- break;
- ssize_t r = waio_return(waio, &cb);
- if (r <= 0)
- break; // EOF or error
mp_input_src_feed_cmd_text(src, buffer, r);
}
-
-done:
- waio_free(waio);
- if (close_fd)
- close(fd);
}
void mp_input_pipe_add(struct input_ctx *ictx, const char *filename)