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.
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.
* 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
static void ShutdownRequestThread(void * arg)
{
HANDLE shutdownEvent = (HANDLE) arg;
- DWORD rv;
WaitForSingleObject(shutdownEvent, INFINITE);
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: