Skip to content

Commit

Permalink
io: support mp_make_wakeup_pipe on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
ruihe774 authored and kasper93 committed Dec 5, 2024
1 parent 91f1f4f commit f753049
Showing 1 changed file with 95 additions and 17 deletions.
112 changes: 95 additions & 17 deletions osdep/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,7 @@ bool mp_set_cloexec(int fd)
return true;
}

#ifdef _WIN32
int mp_make_cloexec_pipe(int pipes[2])
{
pipes[0] = pipes[1] = -1;
return -1;
}
#else
#ifndef _WIN32
int mp_make_cloexec_pipe(int pipes[2])
{
if (pipe(pipes) != 0) {
Expand All @@ -80,14 +74,7 @@ int mp_make_cloexec_pipe(int pipes[2])
mp_set_cloexec(pipes[i]);
return 0;
}
#endif

#ifdef _WIN32
int mp_make_wakeup_pipe(int pipes[2])
{
return mp_make_cloexec_pipe(pipes);
}
#else
// create a pipe, and set it to non-blocking (and also set FD_CLOEXEC)
int mp_make_wakeup_pipe(int pipes[2])
{
Expand All @@ -100,15 +87,13 @@ int mp_make_wakeup_pipe(int pipes[2])
}
return 0;
}
#endif

void mp_flush_wakeup_pipe(int pipe_end)
{
#ifndef _WIN32
char buf[100];
(void)read(pipe_end, buf, sizeof(buf));
#endif
}
#endif

#ifdef _WIN32

Expand Down Expand Up @@ -146,9 +131,13 @@ char *mp_to_utf8(void *talloc_ctx, const wchar_t *s)

#ifdef _WIN32

#include <stdatomic.h>

#include <io.h>
#include <fcntl.h>

#include "osdep/threads.h"
#include "osdep/getpid.h"

static void set_errno_from_lasterror(void)
{
Expand Down Expand Up @@ -878,4 +867,93 @@ void freelocale(locale_t locobj)
{
}

#define MP_PIPE_BUF_SIZE 65536

int mp_make_cloexec_pipe(int pipes[2])
{
if (_pipe(pipes, MP_PIPE_BUF_SIZE, _O_BINARY | _O_NOINHERIT) != 0) {
pipes[0] = pipes[1] = -1;
return -1;
}
return 0;
}

int mp_make_wakeup_pipe(int pipes[2])
{
static atomic_ulong pipe_id = 0;

pipes[0] = pipes[1] = -1;
HANDLE handles[2];
handles[0] = handles[1] = INVALID_HANDLE_VALUE;

const char *pipe_name = mp_tprintf(55, "\\\\?\\pipe\\mpv\\%lu-%lu", mp_getpid(), atomic_fetch_add_explicit(&pipe_id, 1, memory_order_relaxed));

handles[1] = CreateNamedPipeA(
pipe_name,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
0,
1,
MP_PIPE_BUF_SIZE,
MP_PIPE_BUF_SIZE,
0,
NULL
);
if (handles[1] == INVALID_HANDLE_VALUE) {
set_errno_from_lasterror();
goto error;
}

handles[0] = CreateFileA(
pipe_name,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (handles[0] == INVALID_HANDLE_VALUE) {
set_errno_from_lasterror();
goto error;
}

if (!ConnectNamedPipe(handles[1], NULL) && GetLastError() != ERROR_PIPE_CONNECTED) {
set_errno_from_lasterror();
goto error;
}

for (int i = 0; i < 2; i++) {
pipes[i] = _open_osfhandle((intptr_t)handles[i], 0);
if (pipes[i] == -1)
goto error;
}

return 0;

error:
for (int i = 0; i < 2; i++) {
if (pipes[i] != -1) {
_close(pipes[i]);
pipes[i] = -1;
} else if (handles[i] != INVALID_HANDLE_VALUE) {
CloseHandle(handles[i]);
}
}

return -1;
}

void mp_flush_wakeup_pipe(int pipe_end)
{
char buf[100];
OVERLAPPED operation = {};
HANDLE handle = (HANDLE)_get_osfhandle(pipe_end);
if (handle == INVALID_HANDLE_VALUE)
return;
if (!ReadFile(handle, buf, sizeof(buf), NULL, &operation)) {
if (GetLastError() != ERROR_IO_PENDING || !CancelIoEx(handle, &operation))
set_errno_from_lasterror();
}
}

#endif // __MINGW32__

0 comments on commit f753049

Please sign in to comment.