diff options
author | Marc Hoersken <info@marc-hoersken.de> | 2014-01-26 00:58:30 +0100 |
---|---|---|
committer | Marc Hoersken <info@marc-hoersken.de> | 2014-01-26 00:58:30 +0100 |
commit | 49b63cf30d4242b51bd49295f9f20cfbfb641a7d (patch) | |
tree | ae36cb1e00e1d46c68ea957351b03c718c2b7785 /tests | |
parent | f55f8d4c18c857a249f396636c663dee94d65d5b (diff) |
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.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/server/sockfilt.c | 67 |
1 files 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 <netdb.h> #endif -#ifdef USE_WINSOCK -#include <conio.h> /* 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); |