fielding 98/10/05 10:48:45
Modified: src CHANGES
src/main buff.c
Log:
Fix a possible race condition between timed-out requests and the
ap_bhalfduplex select that might result in an infinite loop on
platforms that do not validate the descriptor.
Revision Changes Path
1.1101 +4 -0 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1100
retrieving revision 1.1101
diff -u -r1.1100 -r1.1101
--- CHANGES 1998/10/04 19:05:13 1.1100
+++ CHANGES 1998/10/05 17:48:42 1.1101
@@ -1,5 +1,9 @@
Changes with Apache 1.3.3
+ *) Fix a possible race condition between timed-out requests and the
+ ap_bhalfduplex select that might result in an infinite loop on
+ platforms that do not validate the descriptor. [Roy Fielding]
+
*) Fix mod_autoindex bug where directories got a size of "0k" instead
of "-". [Martin Plechsmid <[EMAIL PROTECTED]>, Marc Slemko]
PR#3130
1.83 +12 -3 apache-1.3/src/main/buff.c
Index: buff.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/buff.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -r1.82 -r1.83
--- buff.c 1998/09/04 16:47:46 1.82
+++ buff.c 1998/10/05 17:48:44 1.83
@@ -562,14 +562,22 @@
#endif
-/* note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE */
+/* Test the descriptor and flush the output buffer if it looks like
+ * we will block on the next read.
+ *
+ * Note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE
+ */
API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
{
int rv;
fd_set fds;
struct timeval tv;
- if (fb->incnt > 0 || fb->outcnt == 0) {
+ /* We don't need to do anything if the connection has been closed
+ * or there is something readable in the incoming buffer
+ * or there is nothing flushable in the output buffer.
+ */
+ if (fb == NULL || fb->fd_in < 0 || fb->incnt > 0 || fb->outcnt == 0) {
return;
}
/* test for a block */
@@ -579,7 +587,8 @@
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
- } while (rv < 0 && errno == EINTR);
+ } while (rv < 0 && errno == EINTR && !(fb->flags & B_EOUT));
+
/* treat any error as if it would block as well */
if (rv != 1) {
ap_bflush(fb);