[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnurl] 117/264: sockfilt: fix handling of ready closed sockets on Windo
From: |
gnunet |
Subject: |
[gnurl] 117/264: sockfilt: fix handling of ready closed sockets on Windows |
Date: |
Thu, 30 Apr 2020 16:07:00 +0200 |
This is an automated email from the git hooks/post-receive script.
nikita pushed a commit to branch master
in repository gnurl.
commit 3d1f35eb13fbf0c16008830d5f8841910b308ee4
Author: Marc Hoersken <address@hidden>
AuthorDate: Sun Mar 29 18:25:31 2020 +0200
sockfilt: fix handling of ready closed sockets on Windows
Replace the incomplete workaround regarding FD_CLOSE
only signalling once by instead doing a pre-check with
standard select and storing the result for later use.
select keeps triggering on closed sockets on Windows while
WSAEventSelect fires only once with data still available.
By doing the pre-check we do not run in a deadlock
due to waiting forever for another FD_CLOSE event.
---
tests/server/sockfilt.c | 60 ++++++++++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 25 deletions(-)
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 9c43f90e4..26bbf416d 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -742,6 +742,7 @@ static HANDLE select_ws_wait(HANDLE handle, HANDLE signal,
return thread;
}
struct select_ws_data {
+ WSANETWORKEVENTS pre; /* the internal select result (indexed by fds/idx) */
curl_socket_t fd; /* the original input handle (indexed by fds/idx) */
curl_socket_t wsasock; /* the internal socket handle (indexed by wsa) */
WSAEVENT wsaevent; /* the internal WINSOCK event (indexed by wsa) */
@@ -752,6 +753,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set
*writefds,
fd_set *exceptfds, struct timeval *timeout)
{
HANDLE abort, mutex, signal, handle, *handles;
+ fd_set readsock, writesock, exceptsock;
DWORD milliseconds, wait, idx;
WSANETWORKEVENTS wsanetevents;
struct select_ws_data *data;
@@ -811,14 +813,24 @@ static int select_ws(int nfds, fd_set *readfds, fd_set
*writefds,
long networkevents = 0;
handles[nfd] = 0;
- if(FD_ISSET(fds, readfds))
+ FD_ZERO(&readsock);
+ FD_ZERO(&writesock);
+ FD_ZERO(&exceptsock);
+
+ if(FD_ISSET(fds, readfds)) {
+ FD_SET(fds, &readsock);
networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE;
+ }
- if(FD_ISSET(fds, writefds))
+ if(FD_ISSET(fds, writefds)) {
+ FD_SET(fds, &writesock);
networkevents |= FD_WRITE|FD_CONNECT;
+ }
- if(FD_ISSET(fds, exceptfds))
- networkevents |= FD_OOB|FD_CLOSE;
+ if(FD_ISSET(fds, exceptfds)) {
+ FD_SET(fds, &exceptsock);
+ networkevents |= FD_OOB;
+ }
/* only wait for events for which we actually care */
if(networkevents) {
@@ -854,6 +866,20 @@ static int select_ws(int nfds, fd_set *readfds, fd_set
*writefds,
handles[nfd] = handle;
data[wsa].wsasock = curlx_sitosk(fds);
data[wsa].wsaevent = wsaevent;
+ data[nfd].pre.lNetworkEvents = 0;
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ /* check if the socket is already ready */
+ if(select(fds + 1, &readsock, &writesock, &exceptsock, tv) == 1) {
+ logmsg("[select_ws] socket %d is ready", fds);
+ WSASetEvent(wsaevent);
+ if(FD_ISSET(fds, &readsock))
+ data[nfd].pre.lNetworkEvents |= FD_READ;
+ if(FD_ISSET(fds, &writesock))
+ data[nfd].pre.lNetworkEvents |= FD_WRITE;
+ if(FD_ISSET(fds, &exceptsock))
+ data[nfd].pre.lNetworkEvents |= FD_OOB;
+ }
wsa++;
}
else {
@@ -919,6 +945,9 @@ static int select_ws(int nfds, fd_set *readfds, fd_set
*writefds,
wsanetevents.lNetworkEvents = 0;
error = WSAEnumNetworkEvents(fds, handle, &wsanetevents);
if(error != SOCKET_ERROR) {
+ /* merge result from pre-check using select */
+ wsanetevents.lNetworkEvents |= data[idx].pre.lNetworkEvents;
+
/* remove from descriptor set if not ready for read/accept/close */
if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)))
FD_CLR(sock, readfds);
@@ -927,17 +956,8 @@ static int select_ws(int nfds, fd_set *readfds, fd_set
*writefds,
if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT)))
FD_CLR(sock, writefds);
- /* HACK:
- * use exceptfds together with readfds to signal
- * that the connection was closed by the client.
- *
- * Reason: FD_CLOSE is only signaled once, sometimes
- * at the same time as FD_READ with data being available.
- * This means that recv/sread is not reliable to detect
- * that the connection is closed.
- */
/* remove from descriptor set if not exceptional */
- if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE)))
+ if(!(wsanetevents.lNetworkEvents & (FD_OOB)))
FD_CLR(sock, exceptfds);
}
}
@@ -1061,9 +1081,6 @@ static bool juggle(curl_socket_t *sockfdp,
else {
/* there's always a socket to wait for */
FD_SET(sockfd, &fds_read);
-#ifdef USE_WINSOCK
- FD_SET(sockfd, &fds_err);
-#endif
maxfd = (int)sockfd;
}
break;
@@ -1074,9 +1091,6 @@ static bool juggle(curl_socket_t *sockfdp,
/* sockfd turns CURL_SOCKET_BAD when our connection has been closed */
if(CURL_SOCKET_BAD != sockfd) {
FD_SET(sockfd, &fds_read);
-#ifdef USE_WINSOCK
- FD_SET(sockfd, &fds_err);
-#endif
maxfd = (int)sockfd;
}
else {
@@ -1254,11 +1268,7 @@ static bool juggle(curl_socket_t *sockfdp,
lograw(buffer, nread_socket);
}
- if(nread_socket <= 0
-#ifdef USE_WINSOCK
- || FD_ISSET(sockfd, &fds_err)
-#endif
- ) {
+ if(nread_socket <= 0) {
logmsg("====> Client disconnect");
if(!write_stdout("DISC\n", 5))
return FALSE;
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [gnurl] 136/264: warnless: remove code block for icc that didn't work, (continued)
- [gnurl] 136/264: warnless: remove code block for icc that didn't work, gnunet, 2020/04/30
- [gnurl] 109/264: vquic/ngtcp2.h: update copyright year range, gnunet, 2020/04/30
- [gnurl] 81/264: openssl: adapt to functions marked as deprecated since version 3, gnunet, 2020/04/30
- [gnurl] 110/264: RELEASE-PROCEDURE.md: run the copyright.pl script!, gnunet, 2020/04/30
- [gnurl] 111/264: RELEASE-NOTES: synced, gnunet, 2020/04/30
- [gnurl] 114/264: CI: increase Azure Pipelines timeouts due to performance issues, gnunet, 2020/04/30
- [gnurl] 141/264: select: remove typecast from SOCKET_WRITABLE/READABLE macros, gnunet, 2020/04/30
- [gnurl] 122/264: CURLINFO_CONDITION_UNMET: return true for 304 http status code, gnunet, 2020/04/30
- [gnurl] 236/264: gnutls: bump lowest supported version to 3.1.10, gnunet, 2020/04/30
- [gnurl] 137/264: configure: remove use of -vec-report0 from CFLAGS with icc, gnunet, 2020/04/30
- [gnurl] 117/264: sockfilt: fix handling of ready closed sockets on Windows,
gnunet <=
- [gnurl] 124/264: KNOWN_BUGS: fixed "USE_UNIX_SOCKETS on Windows", gnunet, 2020/04/30
- [gnurl] 154/264: CI/macos: convert CRLF to LF and align indentation, gnunet, 2020/04/30
- [gnurl] 152/264: server/resolve: remove AI_CANONNAME to make macos tell the truth, gnunet, 2020/04/30
- [gnurl] 213/264: tests/FILEFORMAT: converted to markdown and extended, gnunet, 2020/04/30
- [gnurl] 259/264: doh: Constify some input pointers, gnunet, 2020/04/30
- [gnurl] 161/264: release-notes.pl: detect the start of the references in cleanup mode, gnunet, 2020/04/30
- [gnurl] 214/264: mime: properly check Content-Type even if it has parameters, gnunet, 2020/04/30
- [gnurl] 164/264: tests: add Windows compatible pidwait like pidkill and pidterm, gnunet, 2020/04/30
- [gnurl] 166/264: tests/server/util.c: use curl_off_t instead of long for pid, gnunet, 2020/04/30
- [gnurl] 167/264: compressed.d: stress that the headers are not modified, gnunet, 2020/04/30