From 4a685764a845d5c74a76fcb49a4671f055b8d5f4 Mon Sep 17 00:00:00 2001 From: Ray Satiro Date: Sun, 15 May 2011 21:59:50 +0200 Subject: [PATCH] Ensure sockets are not blocking after a select under Windows. --- src/ChangeLog | 4 ++++ src/connect.c | 18 +++++++++++++++++- src/mswindows.c | 39 ++++++++++++++++++++++++++++++++++++++- src/mswindows.h | 4 ++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index b938538d..33bd3199 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,9 @@ 2011-05-15 Ray Satiro + * connect.c (select_fd) [WINDOWS]: Ensure the socket is blocking. + * mswindows.h: Add declaration for set_windows_fd_as_blocking_socket. + * mswindows.c (set_windows_fd_as_blocking_socket): New function. + * openssl.c (openssl_read): Prevent loops on read errors. 2011-04-24 Giuseppe Scrivano diff --git a/src/connect.c b/src/connect.c index 8f32f984..e12c049a 100644 --- a/src/connect.c +++ b/src/connect.c @@ -656,7 +656,14 @@ select_fd (int fd, double maxtime, int wait_for) tmout.tv_usec = 1000000 * (maxtime - (long) maxtime); do + { result = select (fd + 1, rd, wr, NULL, &tmout); +#ifdef WINDOWS + /* gnulib select() converts blocking sockets to nonblocking in windows. + wget uses blocking sockets so we must convert them back to blocking. */ + set_windows_fd_as_blocking_socket (fd); +#endif + } while (result < 0 && errno == EINTR); return result; @@ -678,6 +685,7 @@ test_socket_open (int sock) { fd_set check_set; struct timeval to; + int ret = 0; /* Check if we still have a valid (non-EOF) connection. From Andrew * Maholski's code in the Unix Socket FAQ. */ @@ -689,7 +697,15 @@ test_socket_open (int sock) to.tv_sec = 0; to.tv_usec = 1; - if (select (sock + 1, &check_set, NULL, NULL, &to) == 0) + ret = select (sock + 1, &check_set, NULL, NULL, &to); +#ifdef WINDOWS +/* gnulib select() converts blocking sockets to nonblocking in windows. +wget uses blocking sockets so we must convert them back to blocking +*/ + set_windows_fd_as_blocking_socket ( sock ); +#endif + + if ( !ret ) /* We got a timeout, it means we're still connected. */ return true; else diff --git a/src/mswindows.c b/src/mswindows.c index d7749fa2..51342300 100644 --- a/src/mswindows.c +++ b/src/mswindows.c @@ -573,7 +573,7 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg) return rc; } - + #ifdef ENABLE_IPV6 /* An inet_ntop implementation that uses WSAAddressToString. Prototype complies with POSIX 1003.1-2004. This is only used under @@ -615,3 +615,40 @@ inet_ntop (int af, const void *src, char *dst, socklen_t cnt) return (const char *) dst; } #endif + + +void +set_windows_fd_as_blocking_socket (int fd) +{ + /* 04/2011 + gnulib select() converts blocking sockets to nonblocking in windows + discussed here: + http://old.nabble.com/blocking-socket-is-nonblocking-after-calling-gnulib- + select%28%29-in-windows-td31432857.html + + wget uses blocking sockets so we must convert them back to blocking. + */ + int ret = 0; + int wsagle = 0; + const int zero = 0; + + do + { + if(wsagle == WSAEINPROGRESS) + Sleep(1); /* use windows sleep */ + + WSASetLastError (0); + ret = ioctl (fd, FIONBIO, &zero); + wsagle = WSAGetLastError(); + } + while (ret && (wsagle == WSAEINPROGRESS)); + + if(ret) + { + fprintf (stderr, + "ioctl() failed. The socket could not be set as blocking.\n" ); + DEBUGP (("Winsock error: %d\n", WSAGetLastError ())); + abort (); + } + return; +} diff --git a/src/mswindows.h b/src/mswindows.h index 82ff5e18..e0a20e4a 100644 --- a/src/mswindows.h +++ b/src/mswindows.h @@ -118,6 +118,9 @@ const char *inet_ntop (int, const void *, char *, socklen_t); # define gai_strerror strerror #endif +/* ioctl needed by set_windows_fd_as_blocking_socket() */ +#include + /* Public functions. */ void ws_startup (void); @@ -125,5 +128,6 @@ void ws_changetitle (const char *); void ws_percenttitle (double); char *ws_mypath (void); void windows_main (char **); +void set_windows_fd_as_blocking_socket (int); #endif /* MSWINDOWS_H */ -- 2.39.2