From 49b63cf30d4242b51bd49295f9f20cfbfb641a7d Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Sun, 26 Jan 2014 00:58:30 +0100 Subject: [PATCH] sockfilt.c: fixed and simplified Windows select function Since the previous complex select function with initial support for non-socket file descriptors, did not actually work correctly for Console handles, this change simplifies the whole procedure by using an internal waiting thread for the stdin console handle. The previous implementation made it continuously trigger for the stdin handle if it was being redirected to a parent process instead of an actual Console input window. This approach supports actual Console input handles as well as anonymous Pipe handles which are used during input redirection. It depends on the fact that ReadFile supports trying to read zero bytes which makes it wait for the handle to become ready for reading. --- tests/server/sockfilt.c | 67 +++++++++++++---------------------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c index d9243319f..a76860880 100644 --- a/tests/server/sockfilt.c +++ b/tests/server/sockfilt.c @@ -92,9 +92,6 @@ #ifdef HAVE_NETDB_H #include #endif -#ifdef USE_WINSOCK -#include /* for _kbhit() used in select_ws() */ -#endif #define ENABLE_CURLX_PRINTF /* make the curlx header define all printf() functions to use the curlx_* @@ -514,16 +511,29 @@ static void lograw(unsigned char *buffer, ssize_t len) * http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx */ +DWORD WINAPI select_ws_stdin_wait_thread(LPVOID lpParameter) +{ + HANDLE handle; + DWORD mode; + + handle = (HANDLE) lpParameter; + + if(GetConsoleMode(handle, &mode)) + WaitForSingleObjectEx(handle, INFINITE, FALSE); + else + ReadFile(handle, NULL, 0, &mode, NULL); + + return 0; +} static int select_ws(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { - long networkevents; - DWORD milliseconds, wait, idx, mode, avail, events, inputs; + DWORD milliseconds, wait, idx, mode; WSAEVENT wsaevent, *wsaevents; WSANETWORKEVENTS wsanetevents; - INPUT_RECORD *inputrecords; HANDLE handle, *handles; curl_socket_t sock, *fdarr, *wsasocks; + long networkevents; int error, fds; DWORD nfd = 0, wsa = 0; int ret = 0; @@ -586,7 +596,10 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds, if(networkevents) { fdarr[nfd] = curlx_sitosk(fds); if(fds == fileno(stdin)) { - handles[nfd] = GetStdHandle(STD_INPUT_HANDLE); + handles[nfd] = CreateThread(NULL, 0, + &select_ws_stdin_wait_thread, + GetStdHandle(STD_INPUT_HANDLE), + 0, NULL); } else if(fds == fileno(stdout)) { handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE); @@ -634,46 +647,8 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds, /* check if the current internal handle was triggered */ if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx && WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) { - /* try to handle the event with STD* handle functions */ + /* first handle stdin, stdout and stderr */ if(fds == fileno(stdin)) { - /* check if there is no data in the input buffer */ - if(!stdin->_cnt) { - /* check if we are getting data from a PIPE */ - if(!GetConsoleMode(handle, &mode)) { - /* check if there is no data from PIPE input */ - if(!PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL)) - avail = 0; - if(!avail) { - FD_CLR(sock, readfds); - /* reduce CPU load */ - Sleep(10); - } - } /* check if there is no data from keyboard input */ - else if (!_kbhit()) { - /* check if there are INPUT_RECORDs in the input buffer */ - if(GetNumberOfConsoleInputEvents(handle, &events)) { - if(events > 0) { - /* remove INPUT_RECORDs from the input buffer */ - inputrecords = (INPUT_RECORD*)malloc(events * - sizeof(INPUT_RECORD)); - if(inputrecords) { - if(!ReadConsoleInput(handle, inputrecords, - events, &inputs)) - inputs = 0; - free(inputrecords); - } - - /* check if we got all inputs, otherwise clear buffer */ - if(events != inputs) - FlushConsoleInputBuffer(handle); - } - } - - /* remove from descriptor set since there is no real data */ - FD_CLR(sock, readfds); - } - } - /* stdin is never ready for write or exceptional */ FD_CLR(sock, writefds); FD_CLR(sock, exceptfds);