summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ross-Gowan <rossymiles@gmail.com>2015-12-07 18:51:33 +1100
committerJames Ross-Gowan <rossymiles@gmail.com>2015-12-20 21:06:02 +1100
commit7558d1ed7b86dbd23504f743d27973556ed68dff (patch)
tree85021c91c3dc91d690636aa3230154b3300cf27d
parent0563eb914f2d4243c00bbd31175658e595dd3763 (diff)
downloadmpv-7558d1ed7b86dbd23504f743d27973556ed68dff.tar.bz2
mpv-7558d1ed7b86dbd23504f743d27973556ed68dff.tar.xz
win32: input: use Vista CancelIoEx
libwaio was added due to the complete inability to cancel synchronous I/O cleanly using the public Windows API in Windows XP. Even calling TerminateThread on the thread performing I/O was a bad solution, because the TerminateThread function in XP would leak the thread's stack. In Vista and up, however, this is no longer a problem. CancelIoEx can cancel synchronous I/O running on other threads, allowing the thread to exit cleanly, so replace libwaio usage with native Vista API functions. It should be noted that this change also removes the hack added in 8a27025 for preventing a deadlock that only seemed to happen in Windows XP. KB2009703 says that Vista and up are not affected by this, due to a change in the implementation of GetFileType, so the hack should not be needed anymore.
-rw-r--r--DOCS/compile-windows.md22
-rwxr-xr-xTOOLS/old-configure1
-rw-r--r--input/input.c4
-rw-r--r--input/pipe-win32.c121
-rw-r--r--wscript6
-rw-r--r--wscript_build.py2
6 files changed, 66 insertions, 90 deletions
diff --git a/DOCS/compile-windows.md b/DOCS/compile-windows.md
index 9acd6e269e..a0e27baf4b 100644
--- a/DOCS/compile-windows.md
+++ b/DOCS/compile-windows.md
@@ -188,25 +188,3 @@ a pthreads wrapper or you want to build mpv without one, configure with:
```bash
./waf configure --enable-win32-internal-pthreads
```
-
-libwaio
--------
-
-If you want to use ``--input-file``, you need libwaio. It's available from
-git://midipix.org/waio
-
-To compile libwaio in MSYS2, run:
-
-```bash
-git clone git://midipix.org/waio && cd waio
-
-# 32-bit build, run from mingw32_shell.bat
-./build-mingw-nt32 lib-static CC=gcc AR=ar
-cp -r include/waio /mingw32/include
-cp lib32/libwaio.a /mingw32/lib
-
-# 64-bit build, run from mingw64_shell.bat
-./build-mingw-nt64 lib-static CC=gcc AR=ar
-cp -r include/waio /mingw64/include
-cp lib64/libwaio.a /mingw64/lib
-```
diff --git a/TOOLS/old-configure b/TOOLS/old-configure
index 6b5635c2e1..3dea7029ed 100755
--- a/TOOLS/old-configure
+++ b/TOOLS/old-configure
@@ -954,7 +954,6 @@ cat > $TMPC << EOF
#define HAVE_GLOB 1
#define HAVE_NANOSLEEP 1
#define HAVE_SDL1 0
-#define HAVE_WAIO 0
#define HAVE_POSIX_SPAWN 1
#define HAVE_GLIBC_THREAD_NAME (!!__GLIBC__)
#define HAVE_OSX_THREAD_NAME 0
diff --git a/input/input.c b/input/input.c
index 5b3370736a..e1dfe2e616 100644
--- a/input/input.c
+++ b/input/input.c
@@ -1265,11 +1265,7 @@ void mp_input_load(struct input_ctx *ictx)
#if defined(__MINGW32__)
if (ictx->global->opts->input_file && *ictx->global->opts->input_file)
-#if HAVE_WAIO
mp_input_pipe_add(ictx, ictx->global->opts->input_file);
-#else
- MP_ERR(ictx, "Pipes not available.\n");
-#endif
#endif
}
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)
diff --git a/wscript b/wscript
index 9d09170fac..00a67009a8 100644
--- a/wscript
+++ b/wscript
@@ -199,12 +199,6 @@ iconv support use --disable-iconv.",
'deps_any': [ 'os-win32', 'os-cygwin' ],
'func': check_true
}, {
- 'name': '--waio',
- 'desc': 'libwaio for win32',
- 'deps': [ 'os-win32', 'mingw' ],
- 'func': check_libs(['waio'],
- check_statement('waio/waio.h', 'waio_alloc(0, 0, 0, 0)')),
- }, {
'name': '--termios',
'desc': 'termios',
'func': check_headers('termios.h', 'sys/termios.h'),
diff --git a/wscript_build.py b/wscript_build.py
index a6ec6795b5..46ff204b59 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -180,7 +180,7 @@ def build(ctx):
( "input/input.c" ),
( "input/ipc.c", "!mingw" ),
( "input/keycodes.c" ),
- ( "input/pipe-win32.c", "waio" ),
+ ( "input/pipe-win32.c", "mingw" ),
## Misc
( "misc/bstr.c" ),