jim 96/07/09 14:44:59
Modified: src http_main.c Log: Adding lingering-close in addition to SO_LINGER Revision Changes Path 1.45 +68 -2 apache/src/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apache/src/http_main.c,v retrieving revision 1.44 retrieving revision 1.45 diff -C3 -r1.44 -r1.45 *** http_main.c 1996/07/09 21:40:14 1.44 --- http_main.c 1996/07/09 21:44:57 1.45 *************** *** 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); *************** *** 1268,1274 **** --- 1322,1335 ---- 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 } } *************** *** 1322,1329 **** 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; --- 1383,1395 ---- exit(1); } ! #ifdef USE_SO_LINGER /* 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; *************** *** 1335,1341 **** exit(1); } } ! #endif /* NEED_LINGER */ if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1) { --- 1401,1407 ---- exit(1); } } ! #endif /* USE_SO_LINGER */ if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1) {