You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Roy Fielding <fi...@hyperreal.com> on 1997/01/25 23:37:18 UTC

cvs commit: apache/src buff.h buff.c http_main.c http_protocol.c

fielding    97/01/25 14:37:17

  Modified:    src       buff.h buff.c http_main.c http_protocol.c
  Log:
  Fixed bug in bcwrite regarding failure to account for partial writes.
  Avoids calling bflush() when the client is pipelining requests.
  Remove unnecessary flushes from http_protocol.
  
  Submitted by: Dean Gaudet
  Reviewed by: Roy Fielding, Alexei Kosut
  
  Revision  Changes    Path
  1.10      +1 -0      apache/src/buff.h
  
  Index: buff.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -C3 -r1.9 -r1.10
  *** buff.h	1997/01/01 18:10:15	1.9
  --- buff.h	1997/01/25 22:37:09	1.10
  ***************
  *** 120,125 ****
  --- 120,126 ----
    extern int bvputs(BUFF *fb, ...);
    extern int bprintf(BUFF *fb,const char *fmt,...);
    extern int vbprintf(BUFF *fb,const char *fmt,va_list vlist);
  + extern int btestread(BUFF *fb);
    
    /* Internal routines */
    extern int bflsbuf(int c, BUFF *fb);
  
  
  
  1.15      +72 -9     apache/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -C3 -r1.14 -r1.15
  *** buff.c	1997/01/20 04:28:07	1.14
  --- buff.c	1997/01/25 22:37:10	1.15
  ***************
  *** 402,407 ****
  --- 402,438 ----
    }
    
    /*
  +  * Tests if there is data to be read.  Returns 0 if there is data,
  +  * -1 otherwise.
  +  */
  + int
  + btestread(BUFF *fb)
  + {
  +     fd_set fds;
  +     struct timeval tv;
  +     int rv;
  + 
  +     /* the simple case, we've already got data in the buffer */
  +     if( fb->incnt ) {
  + 	return( 0 );
  +     }
  + 
  +     /* otherwise see if the descriptor would block if we try to read it */
  +     do {
  + 	FD_ZERO( &fds );
  + 	FD_SET( fb->fd_in, &fds );
  + 	tv.tv_sec = 0;
  + 	tv.tv_usec = 0;
  + #ifdef HPUX
  + 	rv = select( fb->fd_in + 1, (int *)&fds, NULL, NULL, &tv );
  + #else
  + 	rv = select( fb->fd_in + 1, &fds, NULL, NULL, &tv );
  + #endif
  +     } while( rv < 0 && errno == EINTR );
  +     return( rv == 1 ? 0 : -1 );
  + }
  + 
  + /*
     * Skip data until a linefeed character is read
     * Returns 1 on success, 0 if no LF found, or -1 on error
     */
  ***************
  *** 469,474 ****
  --- 500,533 ----
        else return buf[0];
    }
    
  + 
  + /*
  +  * When doing chunked encodings we really have to write everything in the
  +  * chunk before proceeding onto anything else.  This routine either writes
  +  * nbytes and returns 0 or returns -1 indicating a failure.
  +  *
  +  * This is *seriously broken* if used on a non-blocking fd.  It will poll.
  +  */
  + static int
  + write_it_all( int fd, const void *buf, int nbyte ) {
  + 
  +     int i;
  + 
  +     while( nbyte > 0 ) {
  + 	i = write( fd, buf, nbyte );
  + 	if( i == -1 ) {
  + 	    if( errno != EAGAIN && errno != EINTR ) {
  + 		return( -1 );
  + 	    }
  + 	} else {
  + 	    nbyte -= i;
  + 	    buf = i + (const char *)buf;
  + 	}
  +     }
  +     return( 0 );
  + }
  + 
  + 
    /*
     * A hook to write() that deals with chunking. This is really a protocol-
     * level issue, but we deal with it here because it's simpler; this is
  ***************
  *** 476,493 ****
     * 2.0, using something like sfio stacked disciplines or BSD's funopen().
     */
    int bcwrite(BUFF *fb, const void *buf, int nbyte) {
  -     int r;
    
        if (fb->flags & B_CHUNK) {
    	char chunksize[16];	/* Big enough for practically anything */
    
    	ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
  ! 	write(fb->fd, chunksize, strlen(chunksize));
        }
  !     r = write(fb->fd, buf, nbyte);
  !     if ((r > 0) && (fb->flags & B_CHUNK))
  ! 	write(fb->fd, "\015\012", 2);
  !     return r;
    }
    
    /*
  --- 535,557 ----
     * 2.0, using something like sfio stacked disciplines or BSD's funopen().
     */
    int bcwrite(BUFF *fb, const void *buf, int nbyte) {
    
        if (fb->flags & B_CHUNK) {
    	char chunksize[16];	/* Big enough for practically anything */
    
    	ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
  ! 	if( write_it_all(fb->fd, chunksize, strlen(chunksize)) == -1 ) {
  ! 	    return( -1 );
  ! 	}
  ! 	if( write_it_all(fb->fd, buf, nbyte) == -1 ) {
  ! 	    return( -1 );
  ! 	}
  ! 	if( write_it_all(fb->fd, "\015\012", 2) == -1 ) {
  ! 	    return( -1 );
  ! 	}
  ! 	return( nbyte );
        }
  !     return( write(fb->fd, buf, nbyte) );
    }
    
    /*
  ***************
  *** 573,579 ****
    /* we have emptied the file buffer. Now try to write the data from the
     * original buffer until there is less than bufsiz left
     */
  !     while (nbyte > fb->bufsiz)
        {
    	do i = bcwrite(fb, buf, nbyte);
    	while (i == -1 && errno == EINTR);
  --- 637,643 ----
    /* we have emptied the file buffer. Now try to write the data from the
     * original buffer until there is less than bufsiz left
     */
  !     while (nbyte >= fb->bufsiz)
        {
    	do i = bcwrite(fb, buf, nbyte);
    	while (i == -1 && errno == EINTR);
  ***************
  *** 611,617 ****
    int
    bflush(BUFF *fb)
    {
  !     int i, j;
    
        if (!(fb->flags & B_WR) || (fb->flags & B_EOUT)) return 0;
    
  --- 675,681 ----
    int
    bflush(BUFF *fb)
    {
  !     int i;
    
        if (!(fb->flags & B_WR) || (fb->flags & B_EOUT)) return 0;
    
  ***************
  *** 620,626 ****
        while (fb->outcnt > 0)
        {
    /* the buffer must be full */
  - 	j = fb->outcnt;
    	do i = bcwrite(fb, fb->outbase, fb->outcnt);
    	while (i == -1 && errno == EINTR);
    	if (i > 0) fb->bytes_sent += i;
  --- 684,689 ----
  
  
  
  1.113     +5 -2      apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -C3 -r1.112 -r1.113
  *** http_main.c	1997/01/25 20:28:19	1.112
  --- http_main.c	1997/01/25 22:37:11	1.113
  ***************
  *** 1675,1681 ****
            if (r) increment_counts(child_num,r,1);
    #endif
    	while (r && current_conn->keepalive) {
  ! 	    bflush(conn_io);
    	    destroy_pool(r->pool);
    	    (void)update_child_status (child_num, SERVER_BUSY_KEEPALIVE,
    	     (request_rec*)NULL);
  --- 1675,1684 ----
            if (r) increment_counts(child_num,r,1);
    #endif
    	while (r && current_conn->keepalive) {
  ! 	    /* If there's no request waiting for us to read then flush the
  ! 	     * socket.  This is to avoid tickling a bug in older Netscape
  ! 	     * clients. */
  ! 	    if( btestread(conn_io) == -1 ) bflush(conn_io);
    	    destroy_pool(r->pool);
    	    (void)update_child_status (child_num, SERVER_BUSY_KEEPALIVE,
    	     (request_rec*)NULL);
  ***************
  *** 2150,2156 ****
    	if (r) process_request (r); /* else premature EOF (ignore) */
    
            while (r && conn->keepalive) {
  ! 	    bflush(cio);
    	    destroy_pool(r->pool);
                r = read_request (conn);
                if (r) process_request (r);
  --- 2153,2159 ----
    	if (r) process_request (r); /* else premature EOF (ignore) */
    
            while (r && conn->keepalive) {
  ! 	    if( btestread(cio) == -1 ) bflush(cio);
    	    destroy_pool(r->pool);
                r = read_request (conn);
                if (r) process_request (r);
  
  
  
  1.92      +0 -2      apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.91
  retrieving revision 1.92
  diff -C3 -r1.91 -r1.92
  *** http_protocol.c	1997/01/20 04:28:09	1.91
  --- http_protocol.c	1997/01/25 22:37:12	1.92
  ***************
  *** 1371,1378 ****
    	    o+=w;
            }
        }
  - 
  -     if (length > 0) bflush(c->client);
        
        SET_BYTES_SENT(r);
        return total_bytes_sent;
  --- 1371,1376 ----
  
  
  

Re: cvs commit: apache/src buff.h buff.c http_main.c http_protocol.c

Posted by Marc Slemko <ma...@znep.com>.
On Sat, 25 Jan 1997, Roy Fielding wrote:

> fielding    97/01/25 14:37:17
> 
>   Modified:    src       buff.h buff.c http_main.c http_protocol.c
>   Log:
>   Fixed bug in bcwrite regarding failure to account for partial writes.
>   Avoids calling bflush() when the client is pipelining requests.
>   Remove unnecessary flushes from http_protocol.
>   
>   Submitted by: Dean Gaudet
>   Reviewed by: Roy Fielding, Alexei Kosut
>   
>   --- 1675,1684 ----
>             if (r) increment_counts(child_num,r,1);
>     #endif
>     	while (r && current_conn->keepalive) {
>   ! 	    /* If there's no request waiting for us to read then flush the
>   ! 	     * socket.  This is to avoid tickling a bug in older Netscape
>   ! 	     * clients. */
>   ! 	    if( btestread(conn_io) == -1 ) bflush(conn_io);
>     	    destroy_pool(r->pool);
>     	    (void)update_child_status (child_num, SERVER_BUSY_KEEPALIVE,
>     	     (request_rec*)NULL);

Is this one really only for broken Netscape?

Isn't it just a fact of life that if there is no request coming in, stuff
could wait around in our buffer until it is closed if it isn't flushed?