You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Nathan Schrenk <ns...@neog.com> on 1996/01/03 18:28:39 UTC

Timeout code revisited

Hello all,

After sitting down and looking at the timeout code and the send_fd() 
procedure I've come up with a quick fix that seems to correct the 
problems my site was exhibiting.  

The symptom that was showing up was that web users with modems were 
getting their downloads of large files interrupted.  The problem turned 
out to be that the default_handler() procedure sets a timeout and then 
starts sending the file with send_fd().  send_fd() never updates the 
timer, so that the timeout kicks in and the transfer is aborted no matter 
what after the default timeout number of seconds.  Apache ships with a 
Timeout value of 400 seconds in httpd.conf and so anything that takes 
longer than that to transfer will be interrupted.  

The correct thing to do, in my opinion, is to use the timeout mechanism 
to abort a connection after Timeout seconds of inactivity, not after 
Timeout seconds of sending.  I have modified send_fd() in http_protocol.c 
and had to make one change in http_main.c to get this to compile.

In http_main.c I changed the declaration of timeout_name from

  static char *timeout_name;

to

  char *timeout_name;

This is because gcc wouldn't let me put 
  
  extern char *timeout_name;

in send_fd() while the 'static' was still on the declaration in http_main.c.

 
In http_protocol.c I changed send_fd() to the new version below:

long send_fd(FILE *f, request_rec *r)
{
    char buf[IOBUFSIZE];
    long total_bytes_sent;
    register int n,o,w;
    conn_rec *c = r->connection;
    extern char *timeout_name;
 
    total_bytes_sent = 0;
    while (!r->connection->aborted) {
        while ((n= fread(buf, sizeof(char), IOBUFSIZE, f)) < 1
               && ferror(f) && errno == EINTR)
            continue;
        
        if (n < 1) {
            break;
        }
        o=0;
        if (r->bytes_sent != -1) r->bytes_sent += n;
        total_bytes_sent += n;
        
        if (timeout_name)  /* there is a timeout pending */
          while(n && !r->connection->aborted) {
            w=fwrite(&buf[o],sizeof(char),n,c->client);
            if (w)
              alarm(r->server->timeout);  /* reset timeout timer */
            n-=w;
            o+=w;
          }
        else    
          while(n && !r->connection->aborted) {
            w=fwrite(&buf[o],sizeof(char),n,c->client);
            n-=w;
            o+=w;
        }
    }
    fflush(c->client);
    
    return total_bytes_sent;
}

This send_fd() checks to see if there is an timeout active, and if so, it 
resets the timeot counter every time there is a successful write to the 
network.

This fixes the problems we were experiencing, and we haven't found that 
it causes anything to break.  Any thoughts on this and whether its a good 
or bad thing?  Perhaps it could be included in a future release?

Nathan

--
Nathan Schrenk						nschrenk@neog.com
Neoglyphics Media Corp.                              http://www.neog.com/


Re: Timeout code revisited

Posted by Brian Behlendorf <br...@organic.com>.
On Wed, 3 Jan 1996, Nathan Schrenk wrote:
> After sitting down and looking at the timeout code and the send_fd() 
> procedure I've come up with a quick fix that seems to correct the 
> problems my site was exhibiting.  

Woohoo!

Think you could formulate this into a patch file?  Thanks.
I would classify this as a bug, so the fix could appear in 1.0.2.

	Brian

--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
brian@organic.com  brian@hyperreal.com  http://www.[hyperreal,organic].com/