"Roy T. Fielding" <[EMAIL PROTECTED]> writes:
> > I'm sure there's a great reason for setting B_EOUT flag here, but it
> > sure does suck if you have data waiting to be sent to the client since
> > setting B_EOUT convinces ap_bclose() not to write any more data.
>
> It is only set when the connection is aborted or the fd is gone,
> both indicating that we can't write any more data. I think you
> need to figure out why the conditional above it is false and
> then fix the root of the problem. My guess is that
>
> r->connection->aborted
>
> is being set incorrectly somewhere.
r->connection->aborted isn't being set.
We skip the lingering close path and because ap_read_request() returns
NULL (i.e., r is NULL when we see whether to do lingering close). But
current_conn is still valid and current_conn->aborted isn't set.
The client is doing this:
write lastfd "GET /silly?send_chunks HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"
shutdown lastfd 1
read the response
Here is how Apache interacts with this client:
read(3, "GET /silly?send_chunks HTTP/1.1\r"..., 4096) = 52
write(3, "HTTP/1.1 200 OK\r\nDate: Sat, 19 O"..., 152) = 152
writev(3, [{"1400f\r\n", 7}, {"IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"...,
81935}, {"\r\n", 2}], 3) = 81944
write(3, "1 \r\nI\r\n", 8) = 8
select(4, [3], NULL, NULL, {0, 0}) = 1 (in [3], left {0, 0})
select(4, [3], NULL, NULL, {0, 0}) = 1 (in [3], left {0, 0})
read(3, "", 4096) = 0
close(3)
Here is another patch which respects the aborted flag and makes a
semi-gratuitous cleanup so that there is only one set of code for
this.
Index: src/main/http_main.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v
retrieving revision 1.594
diff -u -r1.594 http_main.c
--- src/main/http_main.c 1 Oct 2002 14:24:23 -0000 1.594
+++ src/main/http_main.c 19 Oct 2002 11:32:12 -0000
@@ -4178,6 +4178,34 @@
ap_server_config_defines = ap_make_array(pcommands, 1, sizeof(char *));
}
+/*
+ * Close the connection, being careful to send out whatever is still
+ * in our buffers. If possible, try to avoid a hard close until the
+ * client has ACKed our FIN and/or has stopped sending us data.
+ */
+static void close_connection(request_rec *r, BUFF *conn_io, int aborted)
+{
+#ifdef NO_LINGCLOSE
+ ap_bclose(conn_io); /* just close it */
+#else
+ if (r && r->connection
+ && !r->connection->aborted
+ && r->connection->client
+ && (r->connection->client->fd >= 0)) {
+ lingering_close(r);
+ }
+ else {
+ if (aborted) {
+ /* we've already hit an error doing I/O with client, so
+ * don't try to write any buffered data during ap_bclose()
+ */
+ ap_bsetflag(conn_io, B_EOUT, 1);
+ }
+ ap_bclose(conn_io);
+ }
+#endif /* NO_LINGCLOSE */
+}
+
#ifndef MULTITHREAD
/*****************************************************************
* Child process main loop.
@@ -4646,28 +4674,7 @@
usr1_just_die = 1;
signal(SIGUSR1, usr1_handler);
}
-
- /*
- * Close the connection, being careful to send out whatever is still
- * in our buffers. If possible, try to avoid a hard close until the
- * client has ACKed our FIN and/or has stopped sending us data.
- */
-
-#ifdef NO_LINGCLOSE
- ap_bclose(conn_io); /* just close it */
-#else
- if (r && r->connection
- && !r->connection->aborted
- && r->connection->client
- && (r->connection->client->fd >= 0)) {
-
- lingering_close(r);
- }
- else {
- ap_bsetflag(conn_io, B_EOUT, 1);
- ap_bclose(conn_io);
- }
-#endif
+ close_connection(r, conn_io, current_conn && current_conn->aborted);
}
}
@@ -5954,28 +5961,8 @@
ap_sync_scoreboard_image();
}
- /*
- * Close the connection, being careful to send out whatever is still
- * in our buffers. If possible, try to avoid a hard close until the
- * client has ACKed our FIN and/or has stopped sending us data.
- */
ap_kill_cleanups_for_socket(ptrans, csd);
-
-#ifdef NO_LINGCLOSE
- ap_bclose(conn_io); /* just close it */
-#else
- if (r && r->connection
- && !r->connection->aborted
- && r->connection->client
- && (r->connection->client->fd >= 0)) {
-
- lingering_close(r);
- }
- else {
- ap_bsetflag(conn_io, B_EOUT, 1);
- ap_bclose(conn_io);
- }
-#endif
+ close_connection(r, conn_io, current_conn && current_conn->aborted);
}
ap_destroy_pool(ptrans);
(void) ap_update_child_status(child_num, SERVER_DEAD, NULL);
Thanks for your response!
--
Jeff Trawick | [EMAIL PROTECTED]
Born in Roswell... married an alien...