Skip to content

Commit 49b63cf

Browse files
committed
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.
1 parent f55f8d4 commit 49b63cf

File tree

1 file changed

+21
-46
lines changed

1 file changed

+21
-46
lines changed

tests/server/sockfilt.c

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@
9292
#ifdef HAVE_NETDB_H
9393
#include <netdb.h>
9494
#endif
95-
#ifdef USE_WINSOCK
96-
#include <conio.h> /* for _kbhit() used in select_ws() */
97-
#endif
9895

9996
#define ENABLE_CURLX_PRINTF
10097
/* 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)
514511
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx
515512
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx
516513
*/
514+
DWORD WINAPI select_ws_stdin_wait_thread(LPVOID lpParameter)
515+
{
516+
HANDLE handle;
517+
DWORD mode;
518+
519+
handle = (HANDLE) lpParameter;
520+
521+
if(GetConsoleMode(handle, &mode))
522+
WaitForSingleObjectEx(handle, INFINITE, FALSE);
523+
else
524+
ReadFile(handle, NULL, 0, &mode, NULL);
525+
526+
return 0;
527+
}
517528
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
518529
fd_set *exceptfds, struct timeval *timeout)
519530
{
520-
long networkevents;
521-
DWORD milliseconds, wait, idx, mode, avail, events, inputs;
531+
DWORD milliseconds, wait, idx, mode;
522532
WSAEVENT wsaevent, *wsaevents;
523533
WSANETWORKEVENTS wsanetevents;
524-
INPUT_RECORD *inputrecords;
525534
HANDLE handle, *handles;
526535
curl_socket_t sock, *fdarr, *wsasocks;
536+
long networkevents;
527537
int error, fds;
528538
DWORD nfd = 0, wsa = 0;
529539
int ret = 0;
@@ -586,7 +596,10 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
586596
if(networkevents) {
587597
fdarr[nfd] = curlx_sitosk(fds);
588598
if(fds == fileno(stdin)) {
589-
handles[nfd] = GetStdHandle(STD_INPUT_HANDLE);
599+
handles[nfd] = CreateThread(NULL, 0,
600+
&select_ws_stdin_wait_thread,
601+
GetStdHandle(STD_INPUT_HANDLE),
602+
0, NULL);
590603
}
591604
else if(fds == fileno(stdout)) {
592605
handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -634,46 +647,8 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
634647
/* check if the current internal handle was triggered */
635648
if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx &&
636649
WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) {
637-
/* try to handle the event with STD* handle functions */
650+
/* first handle stdin, stdout and stderr */
638651
if(fds == fileno(stdin)) {
639-
/* check if there is no data in the input buffer */
640-
if(!stdin->_cnt) {
641-
/* check if we are getting data from a PIPE */
642-
if(!GetConsoleMode(handle, &mode)) {
643-
/* check if there is no data from PIPE input */
644-
if(!PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL))
645-
avail = 0;
646-
if(!avail) {
647-
FD_CLR(sock, readfds);
648-
/* reduce CPU load */
649-
Sleep(10);
650-
}
651-
} /* check if there is no data from keyboard input */
652-
else if (!_kbhit()) {
653-
/* check if there are INPUT_RECORDs in the input buffer */
654-
if(GetNumberOfConsoleInputEvents(handle, &events)) {
655-
if(events > 0) {
656-
/* remove INPUT_RECORDs from the input buffer */
657-
inputrecords = (INPUT_RECORD*)malloc(events *
658-
sizeof(INPUT_RECORD));
659-
if(inputrecords) {
660-
if(!ReadConsoleInput(handle, inputrecords,
661-
events, &inputs))
662-
inputs = 0;
663-
free(inputrecords);
664-
}
665-
666-
/* check if we got all inputs, otherwise clear buffer */
667-
if(events != inputs)
668-
FlushConsoleInputBuffer(handle);
669-
}
670-
}
671-
672-
/* remove from descriptor set since there is no real data */
673-
FD_CLR(sock, readfds);
674-
}
675-
}
676-
677652
/* stdin is never ready for write or exceptional */
678653
FD_CLR(sock, writefds);
679654
FD_CLR(sock, exceptfds);

0 commit comments

Comments
 (0)