httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dean gaudet <dgaudet-list-new-ht...@arctic.org>
Subject Re: question about the STATUS entry for lingering close
Date Tue, 11 Apr 2000 16:34:49 GMT
On Tue, 11 Apr 2000, Jeff Trawick wrote:

> >   * Fix lingering close
> >       Status:
> 
> Does 2.0 regress one or more of the solutions in 1.3, or was some
> improvement (other than async I/O) envisioned?

this actually isn't about implementing SO_LINGER stuff... that should be
avoided at all costs -- SO_LINGER works on very few kernels.  actually
i'm tempted to say rip out all the SO_LINGER stuff.

we need lingering_close() re-implemented, it's in main/http_connection.c.

to do that we need to add a shutdown() method to ap_iol_methods, and i
suggest an ap_bshutdown() added to BUFF.

and then lingering_close() needs to be re-implemented something like
the code below.

-dean

/* we now proceed to read from the client until we get EOF, or until
 * MAX_SECS_TO_LINGER has passed.  the reasons for doing this are
 * documented in a draft:
 *
 * http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt
 *
 * in a nutshell -- if we don't make this effort we risk causing
 * TCP RST packets to be sent which can tear down a connection before
 * all the response data has been sent to the client.
 */

static void lingering_close(request_rec *r)
{
    char dummybuf[IOBUFFERSIZE];
    ap_time_t start;
    ap_ssize_t nbytes;
    ap_status_t rc;
    int timeout;

    /* Send any leftover data to the client, but never try to again */

    if (ap_bflush(r->connection->client) != APR_SUCCESS) {
	ap_bclose(r->connection->client);
	return;
    }
    /* XXX: hrm, setting B_EOUT should probably be part of ap_bshutdown() */
    ap_bsetflag(r->connection->client, B_EOUT, 1);

    if (ap_bshutdown(r->connection->client, 1) != APR_SUCCESS
	|| ap_is_aborted(r->connection)) {
	ap_bclose(r->connection->client);
	return;
    }

    start = ap_now();
    timeout = MAX_SECS_TO_LINGER;
    for (;;) {
	ap_bsetopt(r->connection->client, BO_TIMEOUT, &timeout);
	rc = ap_bread(r->connection->client, dummybuf, sizeof(dummybuf), &nbytes);
	if (rc != APR_SUCCESS) break;

	/* how much time has elapsed? */
	timeout = (ap_now() - start) / AP_USEC_PER_SEC;
	if (timeout >= MAX_SECS_TO_LINGER) break;

	/* figure out the new timeout */
	timeout = MAX_SECS_TO_LINGER - timeout;
    } 

    ap_bclose(r->connection->client);
}


Mime
View raw message