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?