httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roy Fielding <field...@hyperreal.com>
Subject cvs commit: apache/src http_main.c
Date Fri, 24 Jan 1997 02:49:59 GMT
fielding    97/01/23 18:49:58

  Modified:    src       http_main.c
  Log:
  Multiple fixes to the lingering_close code in order to avoid being
  interrupted by a stray timeout, to avoid lingering on a connection
  that has already been aborted or never really existed, to ensure that
  we stop lingering as soon as any error condition is received, and to
  prevent beng stuck indefinitely if the read blocks.
  
  Submitted by: Marc Slemko and Roy Fielding
  
  Revision  Changes    Path
  1.109     +62 -29    apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.108
  retrieving revision 1.109
  diff -C3 -r1.108 -r1.109
  *** http_main.c	1997/01/20 04:28:08	1.108
  --- http_main.c	1997/01/24 02:49:57	1.109
  ***************
  *** 109,114 ****
  --- 109,118 ----
    
    #include "explain.h"
    
  + #if !defined(max)
  + #define max(a,b)        (a > b ? a : b)
  + #endif
  + 
    #ifdef __EMX__
        /* Add MMAP style functionality to OS/2 */
        #ifdef HAVE_MMAP
  ***************
  *** 312,368 ****
     */
    
    #ifndef NO_LINGCLOSE
  ! 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 */
    
  !     if ((shutdown (sd, 1)) != 0)
  ! 	log_unixerr("shutdown", NULL, "lingering_close", server_conf);
    
        /* 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...
         */
    
    #ifdef HPUX
  !     while ((select_rv = select (sd + 1, (int*)&fds_read, NULL, (int*)&fds_err,
  ! 				&tv)) > 0) {
    #else
  !     while ((select_rv = select (sd + 1, &fds_read, NULL, &fds_err, &tv)) >
0) {
    #endif
  ! 	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)
    {
  --- 316,396 ----
     */
    
    #ifndef NO_LINGCLOSE
  ! static void lingering_close (request_rec *r)
    {
        int dummybuf[512];
        struct timeval tv;
        fd_set fds, fds_read, fds_err;
        int select_rv = 0, read_rv = 0;
  +     int sd = r->connection->client->fd;
  + 
  +     if (sd < 0)          /* Don't do anything if the socket is invalid */
  +         return;
  + 
  +     kill_timeout(r);     /* Remove any leftover timeouts */
    
        /* Close our half of the connection --- send client a FIN */
    
  !     if ((shutdown(sd, 1)) != 0) {
  ! 	/* if it fails, no need to go through the rest of the routine */
  ! 	log_unixerr("shutdown", NULL, "lingering_close", r->server);
  ! 	close(sd);
  ! 	return;
  !     }
    
        /* Set up to wait for readable data on socket... */
    
  !     FD_ZERO(&fds);
  !     FD_SET(sd, &fds);
    
        /* Wait for readable data or error condition on socket;
  !      * slurp up any data that arrives...  We exit when we go for 
  !      * an interval of tv length without getting any more data, get an
  !      * error from select(), get an exception on sd, get an error or EOF
  !      * on a read, or the timer expires.
         */
    
  +     /* Prevent a slow-drip client from holding us here indefinitely */
  + 
  +     hard_timeout("lingering_close", r);
  + 
  +     do {
  + 	/* If keep_alive_timeout is too low, using it as a timeout
  + 	 * can cause undesirable behavior so pick some pseudo-arbitrary
  + 	 * minimum value, currently 10 seconds.  These parameters are
  +          * reset on each pass, since they may be changed by select.
  + 	 */
  +         tv.tv_sec  = max(r->server->keep_alive_timeout, 10);
  +         tv.tv_usec = 0;
  +         read_rv    = 0;
  +         fds_read   = fds;
  +         fds_err    = fds;
  +     
    #ifdef HPUX
  !         select_rv = select(sd + 1, (int*)&fds_read, NULL, (int*)&fds_err, &tv);
    #else
  !         select_rv = select(sd + 1, &fds_read, NULL, &fds_err, &tv);
    #endif
  !     } while ((select_rv > 0) &&           /* Something to see on socket   
*/
  !              !FD_ISSET(sd, &fds_err) &&   /* that isn't an error condition
*/
  !              FD_ISSET(sd, &fds_read) &&   /* and is worth trying to read 
 */
  !              ((read_rv = read(sd, dummybuf, sizeof dummybuf)) > 0));
    
  !     /* Log any errors that occurred (client close or reset is not an error) */
        
        if (select_rv < 0)
  !         log_unixerr("select", NULL, "lingering_close", r->server);
        else if (read_rv < 0 && errno != ECONNRESET)
  !         log_unixerr("read", NULL, "lingering_close", r->server);
    
        /* Should now have seen final ack.  Safe to finally kill socket */
    
  !     if (close(sd) < 0)
  !         log_unixerr("close", NULL, "lingering_close", r->server);
  ! 
  !     kill_timeout(r);
    }
  ! #endif /* ndef NO_LINGCLOSE */
    
    void usage(char *bin)
    {
  ***************
  *** 1672,1681 ****
    #ifdef NO_LINGCLOSE
    	bclose(conn_io);	/* just close it */
    #else
  ! 	if (r)
  ! 	    lingering_close (conn_io->fd, r->server);
  ! 	else
  ! 	    close (conn_io->fd);
    #endif	
        }    
    }
  --- 1700,1714 ----
    #ifdef NO_LINGCLOSE
    	bclose(conn_io);	/* just close it */
    #else
  !         if (r && !r->connection->aborted) {
  ! 	    /* if the connection was aborted by a soft_timeout, it has
  ! 	     * already been shutdown() so we don't need to go through
  ! 	     * lingering_close
  ! 	     */
  ! 	    lingering_close(r);
  ! 	} else {
  ! 	    close(conn_io->fd);
  ! 	}
    #endif	
        }    
    }
  
  
  

Mime
View raw message