You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Robert S. Thau" <rs...@ai.mit.edu> on 1996/06/28 03:32:06 UTC
Possible SO_LINGER alternative...
Damn, my timing on these things is becoming execrable. Here's a
patch which shows a technique which is at least alleged in some
quarters to work as well as SO_LINGER, without causing quite so
many problems as are encountered in SO_LINGER alternatives. I'm
running with a SunOS server compiled with -DNEED_LINGER and with
this patch in overnight, and so far, at least, it doesn't seem
to be causing any untoward behavior.
The *interesting* questions, of course, are:
1) Does it also solve the "truncated data" problems which
seem to be solved by setting the real SO_LINGER option on
certain SVR4 derivatives?
2) Does it avoid the problem with processes seemingly idling
indefinitely which may or may not be caused by SO_LINGER?
... and I'm not in *any* position to test either of those things
here.
Again, sorry about the timing foax...
rst
*** http_main.c~ Thu Jun 13 16:33:02 1996
--- http_main.c Thu Jun 27 21:19:11 1996
***************
*** 271,276 ****
--- 271,330 ----
#define accept_mutex_off()
#endif
+ /*
+ * More machine-dependant networking gooo... on some systems,
+ * you've got to be *really* sure that all the packets are acknowledged
+ * before closing the connection. Actually, it shouldn't hurt anyplace,
+ * but this is a late bugfix, so be conservative...
+ */
+
+ #ifdef NEED_LINGER
+ static void lingering_close (int sd, server_rec *server_conf)
+ {
+ int dummybuf[512];
+ struct timeval tv;
+ fd_set fds, fds_read, fds_err;
+ int select_rv = 0, read_rv = 0;
+
+ /* Close our half of the connection --- send client a FIN */
+
+ shutdown (sd, 1);
+
+ /* Set up to wait for readable data on socket... */
+
+ FD_ZERO (&fds);
+ FD_SET (sd, &fds);
+ tv.tv_sec = server_conf->keep_alive_timeout;
+ tv.tv_usec = 0;
+
+ fds_read = fds; fds_err = fds;
+
+ /* Wait for readable data or error condition on socket;
+ * slurp up any data that arrives...
+ */
+
+ while ((select_rv = select (sd + 1, &fds_read, NULL, &fds_err, &tv)) > 0) {
+ if ((read_rv = read (sd, dummybuf, sizeof(dummybuf))) <= 0)
+ break;
+ else {
+ fds_read = fds; fds_err = fds;
+ }
+ }
+
+ /* Log any errors that occured (client closing their end isn't an error) */
+
+ if (select_rv < 0)
+ log_unixerr("select", NULL, "lingering_close", server_conf);
+ else if (read_rv < 0 && errno != ECONNRESET)
+ log_unixerr("read", NULL, "lingering_close", server_conf);
+
+ /* Should now have seen final ack. Safe to finally kill socket */
+
+ shutdown (sd, 2);
+ close (sd);
+ }
+ #endif
+
void usage(char *bin)
{
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
***************
*** 1258,1264 ****
--- 1312,1325 ----
bytes_in_pool (ptrans), r->the_request);
#endif
bflush(conn_io);
+ #ifdef NEED_LINGER
+ if (r)
+ lingering_close (conn_io->fd, r->server);
+ else
+ close (conn_io->fd);
+ #else
bclose(conn_io);
+ #endif
}
}
***************
*** 1312,1319 ****
exit(1);
}
! #ifdef NEED_LINGER /* If puts don't complete, you could try this. */
{
struct linger li;
li.l_onoff = 1;
li.l_linger = 900;
--- 1373,1385 ----
exit(1);
}
! #ifdef NOTDEF /* If puts don't complete, you could try this. */
{
+ /* Unfortunately, SO_LINGER causes problems as severe as it
+ * cures on many of the affected systems; now trying the
+ * lingering_close trick (see routine by that name above)
+ * instead...
+ */
struct linger li;
li.l_onoff = 1;
li.l_linger = 900;