shutdown() the send side and then read() from client until EOF
robs [Tue, 5 Mar 2002 18:15:15 +0000 (18:15 +0000)]
or a timeout expires.  This is done to minimize the potential
that a TCP RST will be sent by our TCP stack in response to
receipt of additional data from the client.  The RST would
cause the client to discard potentially useful response data.

README
libfcgi/os_win32.c

diff --git a/README b/README
index c3b535c..b3bfdf6 100755 (executable)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 FastCGI Developer's Kit README
 ------------------------------
 
-    $Id: README,v 1.19 2002/03/04 22:16:40 robs Exp $
+    $Id: README,v 1.20 2002/03/05 18:15:17 robs Exp $
     Copyright (c) 1996 Open Market, Inc.
     See the file "LICENSE.TERMS" for information on usage and redistribution
     of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -32,8 +32,9 @@ on http://fastcgi.com/.
 2.2.3
 -----
 
- *) [WIN32] shutdown only the send side of a TCP socket to prevent a TCP
-    reset from trashing the reciept of data on the client.
+ *) When closing connections, shutdown() the send side of TCP sockets to 
+    prevent a TCP RST from trashing the reciept of data on the client (when
+    the client continues to send data to the application).
 
  *) [WIN32] force an exit from the ShutdownRequestThread when a shutdown is
     signaled and NamedPipes are in use.
index 7f5add8..294b17f 100755 (executable)
@@ -17,7 +17,7 @@
  *  significantly more enjoyable.)
  */
 #ifndef lint
-static const char rcsid[] = "$Id: os_win32.c,v 1.32 2002/03/04 22:16:38 robs Exp $";
+static const char rcsid[] = "$Id: os_win32.c,v 1.33 2002/03/05 18:15:15 robs Exp $";
 #endif /* not lint */
 
 #define WIN32_LEAN_AND_MEAN 
@@ -272,7 +272,6 @@ void OS_ShutdownPending(void)
 static void ShutdownRequestThread(void * arg)
 {
     HANDLE shutdownEvent = (HANDLE) arg;
-    DWORD rv; 
     
     WaitForSingleObject(shutdownEvent, INFINITE);
 
@@ -1373,14 +1372,38 @@ int OS_Close(int fd)
 
     case FD_SOCKET_SYNC:
        case FD_SOCKET_ASYNC:
-           /*
-            * Closing a socket that has an async read outstanding causes a
-            * tcp reset and possible data loss.  The shutdown call seems to
-            * prevent this.
-            */
-           shutdown(fdTable[fd].fid.sock, SD_SEND);
-           if (closesocket(fdTable[fd].fid.sock) == SOCKET_ERROR) ret = -1;
-           break;
+
+        /*
+         * shutdown() the send side and then read() from client until EOF
+         * or a timeout expires.  This is done to minimize the potential
+         * that a TCP RST will be sent by our TCP stack in response to 
+         * receipt of additional data from the client.  The RST would
+         * cause the client to discard potentially useful response data.
+         */
+
+        if (shutdown(fdTable[fd].fid.sock, SD_SEND) == 0)
+        {
+            struct timeval tv;
+            fd_set rfds;
+            int sock = fdTable[fd].fid.sock;
+            int rv;
+            char trash[1024];
+   
+            FD_ZERO(&rfds);
+
+            do 
+            {
+                   FD_SET(sock, &rfds);
+                   tv.tv_sec = 2;
+                   tv.tv_usec = 0;
+                   rv = select(sock + 1, &rfds, NULL, NULL, &tv);
+            }
+            while (rv > 0 && recv(sock, trash, sizeof(trash), 0) > 0);
+        }
+        
+        closesocket(fdTable[fd].fid.sock);
+
+        break;
 
        default: