>From 40fc0f1cbc5184fca75fb955313caa8de430a2b2 Mon Sep 17 00:00:00 2001
From: Akash Rawal
Date: Wed, 24 May 2017 09:08:34 +0530
Subject: [PATCH] * lib/select.c: Make select() multi-thread safe in windows
---
lib/select.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
modules/select | 1 +
2 files changed, 81 insertions(+), 12 deletions(-)
diff --git a/lib/select.c b/lib/select.c
index ac86c499d..ad704e11f 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
/* Get the overridden 'struct timeval'. */
#include
@@ -105,6 +106,15 @@ IsSocketHandle (HANDLE h)
/* Compute output fd_sets for libc descriptor FD (whose Windows handle is
H). */
+gl_once_define(static, windows_poll_handle_once)
+static PNtQueryInformationFile NtQueryInformationFile;
+void
+static windows_poll_handle_init()
+{
+ NtQueryInformationFile = (PNtQueryInformationFile)
+ GetProcAddress (GetModuleHandle ("ntdll.dll"),
+ "NtQueryInformationFile");
+}
static int
windows_poll_handle (HANDLE h, int fd,
@@ -119,8 +129,6 @@ windows_poll_handle (HANDLE h, int fd,
BOOL bRet;
IO_STATUS_BLOCK iosb;
FILE_PIPE_LOCAL_INFORMATION fpli;
- static PNtQueryInformationFile NtQueryInformationFile;
- static BOOL once_only;
read = write = except = FALSE;
switch (GetFileType (h))
@@ -131,13 +139,7 @@ windows_poll_handle (HANDLE h, int fd,
break;
case FILE_TYPE_PIPE:
- if (!once_only)
- {
- NtQueryInformationFile = (PNtQueryInformationFile)
- GetProcAddress (GetModuleHandle ("ntdll.dll"),
- "NtQueryInformationFile");
- once_only = TRUE;
- }
+ glthread_once(&windows_poll_handle_once, windows_poll_handle_init);
if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
{
@@ -240,13 +242,77 @@ windows_poll_handle (HANDLE h, int fd,
return ret;
}
+static struct
+{
+ HANDLE *data;
+ size_t len;
+ size_t alloc_len;
+} event_pool = {NULL, 0, 8};
+gl_lock_define_initialized(static, event_pool_lock)
+
+static HANDLE
+get_hevent()
+{
+ HANDLE res;
+
+ glthread_lock_lock(&event_pool_lock);
+
+ if (event_pool.len)
+ {
+ event_pool.len--;
+ res = event_pool.data[event_pool.len];
+ }
+ else
+ {
+ res = CreateEvent (NULL, FALSE, FALSE, NULL);
+ }
+
+ glthread_lock_unlock(&event_pool_lock);
+
+ return res;
+}
+
+static void
+return_hevent(HANDLE v)
+{
+ glthread_lock_lock(&event_pool_lock);
+
+ event_pool.len++;
+
+ if (! event_pool.data)
+ {
+ event_pool.data = malloc(sizeof(HANDLE) * event_pool.alloc_len);
+ if (! event_pool.data)
+ {
+ fprintf(stderr, "Failed to allocate memory\n");
+ abort();
+ }
+ }
+
+ if (event_pool.len > event_pool.alloc_len)
+ {
+ event_pool.alloc_len *= 2;
+ event_pool.data = realloc(event_pool.data,
+ sizeof(HANDLE) * event_pool.alloc_len);
+ if (! event_pool.data)
+ {
+ fprintf(stderr, "Failed to allocate memory\n");
+ abort();
+ }
+ }
+
+ event_pool.data[event_pool.len - 1] = v;
+
+ glthread_lock_unlock(&event_pool_lock);
+}
+
int
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
struct timeval *timeout)
#undef timeval
{
static struct timeval tv0;
- static HANDLE hEvent;
+ HANDLE hEvent;
HANDLE h, handle_array[FD_SETSIZE + 2];
fd_set handle_rfds, handle_wfds, handle_xfds;
struct bitset rbits, wbits, xbits;
@@ -273,8 +339,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
}
}
- if (!hEvent)
- hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+ hEvent = get_hevent();
handle_array[0] = hEvent;
nhandles = 1;
@@ -346,6 +411,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
if (!h)
{
errno = EBADF;
+ return_hevent(hEvent);
return -1;
}
@@ -528,6 +594,8 @@ restart:
}
}
+ return_hevent(hEvent);
+
return rc;
}
diff --git a/modules/select b/modules/select
index 28c89ee9c..ced86a162 100644
--- a/modules/select
+++ b/modules/select
@@ -12,6 +12,7 @@ dup2 [test $REPLACE_SELECT = 1]
sockets [test $REPLACE_SELECT = 1]
sys_time [test $REPLACE_SELECT = 1]
msvc-nothrow [test $REPLACE_SELECT = 1]
+lock [test $REPLACE_SELECT = 1]
configure.ac:
gl_FUNC_SELECT
--
2.13.0