>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