httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <field...@kiwi.ICS.UCI.EDU>
Subject Re: [PATCH] Handle timeouts in buffers as well as connection
Date Sun, 20 Apr 1997 11:52:34 GMT
I spent the night trying to understand why we don't get a SIGPIPE
on Solaris 2.5 after the user presses Stop on the client.  According
to netstat, the socket is closing properly, but we just continue writing
until the request times out (my patch is needed for the time out)
because the server process never receives a SIGPIPE and the write
never returns EPIPE.  As far as I can tell, Solaris is just broken
in this regard.

However, in the process, I did find a few more problems with the
timeout code, so I have re-generated my patch below.  This patch does
fix the problem in PR#373, though we'd be better off with a SIGPIPE.

If a soft timeout (or lingerout) occurs while trying to flush a
buffer or write inside buff.c or fread'ing from a CGI's output,
then the timeout would be ignored.  This fix is rather nasty,
since what we would really like to do is flush the output if we
timeout on a read, but we can't do that without differentiating
between read and write timeouts, and we can't do that without
rewriting most of the server.

What we really need is a global (per-thread) timeout that sets a
single flag, and then have all of our code check for that flag and
recover gracefully based upon what it was trying to do at the time.
However, that might be subject to race conditions as well, so we
might just need to replace all of our generic timeouts with more
sophisticated timeouts, each with its own sigsetjmp handling.
Something to remember for 1.2.

.....Roy

Index: buff.c
===================================================================
RCS file: /export/home/cvs/apache/src/buff.c,v
retrieving revision 1.23
diff -c -r1.23 buff.c
*** buff.c	1997/03/04 21:44:38	1.23
--- buff.c	1997/04/20 11:21:27
***************
*** 191,201 ****
      char chunksize[16];	/* Big enough for practically anything */
      int chunk_header_size;
  
!     if( fb->outchunk != -1 ) {
  	/* already chunking */
  	return;
      }
!     if( !(fb->flags & B_WR) ) {
  	/* unbuffered writes */
  	return;
      }
--- 191,201 ----
      char chunksize[16];	/* Big enough for practically anything */
      int chunk_header_size;
  
!     if (fb->outchunk != -1) {
  	/* already chunking */
  	return;
      }
!     if (!(fb->flags & B_WR) || (fb->flags & (B_WRERR|B_EOUT))) {
  	/* unbuffered writes */
  	return;
      }
***************
*** 609,630 ****
   * 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 );
  }
  
  
--- 609,636 ----
   * This is *seriously broken* if used on a non-blocking fd.  It will poll.
   */
  static int
! write_it_all(BUFF *fb, const void *buf, int nbyte)
! {
      int i;
  
!     if (fb->flags & (B_WRERR|B_EOUT))
! 	return -1;
! 
!     while (nbyte > 0) {
! 	i = write(fb->fd, buf, nbyte);
! 	if (i < 0) {
! 	    if (errno != EAGAIN && errno != EINTR) {
! 		return -1;
  	    }
! 	}
! 	else {
  	    nbyte -= i;
  	    buf = i + (const char *)buf;
  	}
+ 	if (fb->flags & B_EOUT)
+ 	    return -1;
      }
!     return 0;
  }
  
  
***************
*** 635,665 ****
   * 2.0, using something like sfio stacked disciplines or BSD's funopen().
   */
  static int
! bcwrite(BUFF *fb, const void *buf, int nbyte) {
! 
      char chunksize[16];	/* Big enough for practically anything */
  #ifndef NO_WRITEV
      struct iovec vec[3];
      int i, rv;
  #endif
  
!     if( !(fb->flags & B_CHUNK) ) return write( fb->fd, buf, nbyte );
  
  #ifdef NO_WRITEV
      /* without writev() this has poor performance, too bad */
  
      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 );
  #else
  #define NVEC	(sizeof(vec)/sizeof(vec[0]))
  
      vec[0].iov_base = chunksize;
--- 641,673 ----
   * 2.0, using something like sfio stacked disciplines or BSD's funopen().
   */
  static int
! bcwrite(BUFF *fb, const void *buf, int nbyte)
! {
      char chunksize[16];	/* Big enough for practically anything */
  #ifndef NO_WRITEV
      struct iovec vec[3];
      int i, rv;
  #endif
  
!     if (fb->flags & (B_WRERR|B_EOUT))
! 	return -1;
! 
!     if (!(fb->flags & B_CHUNK))
! 	return write(fb->fd, buf, nbyte);
  
  #ifdef NO_WRITEV
      /* without writev() this has poor performance, too bad */
  
      ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
!     if (write_it_all(fb, chunksize, strlen(chunksize)) == -1)
! 	return -1;
!     if (write_it_all(fb, buf, nbyte) == -1)
! 	return -1;
!     if (write_it_all(fb, "\015\012", 2) == -1)
! 	return -1;
!     return nbyte;
  #else
+ 
  #define NVEC	(sizeof(vec)/sizeof(vec[0]))
  
      vec[0].iov_base = chunksize;
***************
*** 674,685 ****
       */
      for( i = 0; i < NVEC; ) {
  	do rv = writev( fb->fd, &vec[i], NVEC - i );
! 	while ( rv == -1 && errno == EINTR );
! 	if( rv == -1 ) {
! 	    return( -1 );
! 	}
  	/* recalculate vec to deal with partial writes */
! 	while( rv > 0 ) {
  	    if( rv <= vec[i].iov_len ) {
  		vec[i].iov_base = (char *)vec[i].iov_base + rv;
  		vec[i].iov_len -= rv;
--- 682,692 ----
       */
      for( i = 0; i < NVEC; ) {
  	do rv = writev( fb->fd, &vec[i], NVEC - i );
! 	while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! 	if (rv == -1)
! 	    return -1;
  	/* recalculate vec to deal with partial writes */
! 	while (rv > 0) {
  	    if( rv <= vec[i].iov_len ) {
  		vec[i].iov_base = (char *)vec[i].iov_base + rv;
  		vec[i].iov_len -= rv;
***************
*** 692,700 ****
  		++i;
  	    }
  	}
      }
      /* if we got here, we wrote it all */
!     return( nbyte );
  #undef NVEC
  #endif
  }
--- 699,709 ----
  		++i;
  	    }
  	}
+ 	if (fb->flags & B_EOUT)
+ 	    return -1;
      }
      /* if we got here, we wrote it all */
!     return nbyte;
  #undef NVEC
  #endif
  }
***************
*** 720,734 ****
  /* unbuffered write -- have to use bcwrite since we aren't taking care
   * of chunking any other way */
  	do i = bcwrite(fb, buf, nbyte);
! 	while (i == -1 && errno == EINTR);
! 	if (i > 0) fb->bytes_sent += i;
! 	if (i == 0)
! 	{
! 	    i = -1;  /* return of 0 means non-blocking */
  	    errno = EAGAIN;
  	}
! 	if (i == -1 && errno != EAGAIN) doerror(fb, B_WR);
! 	return i;
      }
  
  /*
--- 729,749 ----
  /* unbuffered write -- have to use bcwrite since we aren't taking care
   * of chunking any other way */
  	do i = bcwrite(fb, buf, nbyte);
! 	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! 	if (i == 0) {  /* return of 0 means non-blocking */
  	    errno = EAGAIN;
+ 	    return -1;
  	}
! 	else if (i < 0) {
! 	    if (errno != EAGAIN)
! 	        doerror(fb, B_WR);
! 	    return -1;
! 	}
! 	fb->bytes_sent += i;
! 	if (fb->flags & B_EOUT)
! 	    return -1;
! 	else
! 	    return i;
      }
  
  /*
***************
*** 752,783 ****
  	}
  
  /* the buffer must be full */
! 	if( fb->flags & B_CHUNK ) {
  	    end_chunk(fb);
  	    /* it is just too painful to try to re-cram the buffer while
  	     * chunking
  	     */
! 	    i = write_it_all( fb->fd, fb->outbase, fb->outcnt )
! 		    ? -1 : fb->outcnt;
! 	} else {
! 	    do i = write(fb->fd, fb->outbase, fb->outcnt);
! 	    while (i == -1 && errno == EINTR);
  	}
! 	if (i > 0) fb->bytes_sent += i;
! 	if (i == 0)
! 	{
! 	    i = -1;  /* return of 0 means non-blocking */
! 	    errno = EAGAIN;
  	}
! 	if (i == -1)
! 	{
! 	    if (nwr == 0)
! 	    {
  		if (errno != EAGAIN) doerror(fb, B_WR);
  		return -1;
  	    }
  	    else return nwr;
  	}
  
  	/* deal with a partial write */
  	if (i < fb->outcnt)
--- 767,794 ----
  	}
  
  /* the buffer must be full */
! 	if (fb->flags & B_CHUNK) {
  	    end_chunk(fb);
  	    /* it is just too painful to try to re-cram the buffer while
  	     * chunking
  	     */
! 	    i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
! 	            -1 : fb->outcnt;
  	}
! 	else {
! 	    do i = write(fb->fd, fb->outbase, fb->outcnt);
! 	    while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  	}
! 	if (i <= 0) {
! 	    if (i == 0) /* return of 0 means non-blocking */
! 	        errno = EAGAIN;
! 	    if (nwr == 0) {
  		if (errno != EAGAIN) doerror(fb, B_WR);
  		return -1;
  	    }
  	    else return nwr;
  	}
+ 	fb->bytes_sent += i;
  
  	/* deal with a partial write */
  	if (i < fb->outcnt)
***************
*** 786,793 ****
  	    unsigned char *x=fb->outbase;
  	    for (j=i; j < n; j++) x[j-i] = x[j];
  	    fb->outcnt -= i;
! 	} else
  	    fb->outcnt = 0;
      }
  /* we have emptied the file buffer. Now try to write the data from the
   * original buffer until there is less than bufsiz left.  Note that we
--- 797,808 ----
  	    unsigned char *x=fb->outbase;
  	    for (j=i; j < n; j++) x[j-i] = x[j];
  	    fb->outcnt -= i;
! 	}
! 	else
  	    fb->outcnt = 0;
+ 
+ 	if (fb->flags & B_EOUT)
+ 	    return -1;
      }
  /* we have emptied the file buffer. Now try to write the data from the
   * original buffer until there is less than bufsiz left.  Note that we
***************
*** 797,822 ****
      while (nbyte >= fb->bufsiz)
      {
  	do i = bcwrite(fb, buf, nbyte);
! 	while (i == -1 && errno == EINTR);
! 	if (i > 0) fb->bytes_sent += i;
! 	if (i == 0)
! 	{
! 	    i = -1;  /* return of 0 means non-blocking */
! 	    errno = EAGAIN;
! 	}
! 	if (i == -1)
! 	{
! 	    if (nwr == 0)
! 	    {
  		if (errno != EAGAIN) doerror(fb, B_WR);
  		return -1;
  	    }
  	    else return nwr;
  	}
  
  	buf = i + (const char *)buf;
  	nwr += i;
  	nbyte -= i;
      }
  /* copy what's left to the file buffer */
      fb->outcnt = 0;
--- 812,835 ----
      while (nbyte >= fb->bufsiz)
      {
  	do i = bcwrite(fb, buf, nbyte);
! 	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! 	if (i <= 0) {
! 	    if (i == 0) /* return of 0 means non-blocking */
! 	        errno = EAGAIN;
! 	    if (nwr == 0) {
  		if (errno != EAGAIN) doerror(fb, B_WR);
  		return -1;
  	    }
  	    else return nwr;
  	}
+ 	fb->bytes_sent += i;
  
  	buf = i + (const char *)buf;
  	nwr += i;
  	nbyte -= i;
+ 
+ 	if (fb->flags & B_EOUT)
+ 	    return -1;
      }
  /* copy what's left to the file buffer */
      fb->outcnt = 0;
***************
*** 840,868 ****
  
      if (fb->flags & B_WRERR) return -1;
      
!     if( fb->flags & B_CHUNK ) end_chunk(fb);
  
      while (fb->outcnt > 0)
      {
! /* the buffer must be full */
  	do i = write(fb->fd, fb->outbase, fb->outcnt);
! 	while (i == -1 && errno == EINTR);
! 	if (i > 0) fb->bytes_sent += i;
! 	if (i == 0)
! 	{
  	    errno = EAGAIN;
  	    return -1;  /* return of 0 means non-blocking */
  	}
! 	if (i == -1)
! 	{
  	    if (errno != EAGAIN) doerror(fb, B_WR);
  	    return -1;
  	}
  
! /*
!  * we should have written all the data, however if the fd was in a
!  * strange (non-blocking) mode, then we might not have done so.
!  */
  	if (i < fb->outcnt)
  	{
  	    int j, n=fb->outcnt;
--- 853,879 ----
  
      if (fb->flags & B_WRERR) return -1;
      
!     if (fb->flags & B_CHUNK) end_chunk(fb);
  
      while (fb->outcnt > 0)
      {
! 	/* the buffer must be full */
  	do i = write(fb->fd, fb->outbase, fb->outcnt);
! 	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! 	if (i == 0) {
  	    errno = EAGAIN;
  	    return -1;  /* return of 0 means non-blocking */
  	}
! 	else if (i < 0) {
  	    if (errno != EAGAIN) doerror(fb, B_WR);
  	    return -1;
  	}
+ 	fb->bytes_sent += i;
  
! 	/*
!  	 * We should have written all the data, but if the fd was in a
!  	 * strange (non-blocking) mode, then we might not have done so.
!  	 */
  	if (i < fb->outcnt)
  	{
  	    int j, n=fb->outcnt;
***************
*** 870,875 ****
--- 881,892 ----
  	    for (j=i; j < n; j++) x[j-i] = x[j];
  	}
  	fb->outcnt -= i;
+ 
+ 	/* If a soft timeout occurs while flushing, the handler should
+ 	 * have set the buffer flag B_EOUT.
+ 	 */
+ 	if (fb->flags & B_EOUT)
+ 	    return -1;
      }
      return 0;
  }
Index: http_main.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.h,v
retrieving revision 1.8
diff -c -r1.8 http_main.h
*** http_main.h	1997/01/01 18:10:20	1.8
--- http_main.h	1997/04/20 11:21:27
***************
*** 96,98 ****
--- 96,112 ----
  int get_child_status (int child_num);
  int count_busy_servers ();
  int count_idle_servers ();
+ 
+ /*
+  * Replace signal function with sigaction equivalent
+  */
+ #ifndef NO_USE_SIGACTION
+ typedef void Sigfunc(int);
+ 
+ #if defined(SIG_IGN) && !defined(SIG_ERR)
+ #define SIG_ERR ((Sigfunc *)-1)
+ #endif
+ 
+ Sigfunc *signal(int signo, Sigfunc *func);
+ #endif
+ 
Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.c,v
retrieving revision 1.137
diff -c -r1.137 http_main.c
*** http_main.c	1997/04/12 04:24:57	1.137
--- http_main.c	1997/04/20 11:21:27
***************
*** 325,332 ****
  static int alarms_blocked = 0;
  static int alarm_pending = 0;
  
! void timeout(sig)			/* Also called on SIGPIPE */
! int sig;
  {
      char errstr[MAX_STRING_LEN];
      void *dirconf;
--- 325,353 ----
  static int alarms_blocked = 0;
  static int alarm_pending = 0;
  
! #ifndef NO_USE_SIGACTION
! /*
!  * Replace standard signal() with the more reliable sigaction equivalent
!  * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
!  * (the version that does not automatically restart system calls).
!  */
! Sigfunc *signal(int signo, Sigfunc *func)
! {
!     struct sigaction act, oact;
! 
!     act.sa_handler = func;
!     sigemptyset(&act.sa_mask);
!     act.sa_flags = 0;
! #ifdef  SA_INTERRUPT    /* SunOS */
!     act.sa_flags |= SA_INTERRUPT;
! #endif
!     if (sigaction(signo, &act, &oact) < 0)
!        return SIG_ERR;
!     return oact.sa_handler;
! }
! #endif
! 
! void timeout(int sig)			/* Also called on SIGPIPE */
  {
      char errstr[MAX_STRING_LEN];
      void *dirconf;
***************
*** 376,383 ****
  	if (!current_conn->keptalive) 
              log_transaction(log_req);
  
!         if (sig == SIGPIPE)
!             bsetflag(timeout_req->connection->client, B_EOUT, 1);
  	bclose(timeout_req->connection->client);
      
  	if (!standalone) exit(0);
--- 397,403 ----
  	if (!current_conn->keptalive) 
              log_transaction(log_req);
  
! 	bsetflag(timeout_req->connection->client, B_EOUT, 1);
  	bclose(timeout_req->connection->client);
      
  	if (!standalone) exit(0);
***************
*** 388,397 ****
  #endif
      }
      else {   /* abort the connection */
!         if (sig == SIGPIPE)
!             bsetflag(current_conn->client, B_EOUT, 1);
!         else
!             bflush(current_conn->client);
          current_conn->aborted = 1;
      }
  }
--- 408,414 ----
  #endif
      }
      else {   /* abort the connection */
!         bsetflag(current_conn->client, B_EOUT, 1);
          current_conn->aborted = 1;
      }
  }
***************
*** 419,425 ****
      timeout_req = r;
      timeout_name = name;
      
!     signal(SIGALRM,(void (*)())timeout);
      if (r->connection->keptalive) 
         alarm (r->server->keep_alive_timeout);
      else
--- 436,442 ----
      timeout_req = r;
      timeout_name = name;
      
!     signal(SIGALRM, timeout);
      if (r->connection->keptalive) 
         alarm (r->server->keep_alive_timeout);
      else
***************
*** 431,437 ****
      timeout_req = r;
      timeout_name = name;
      
!     signal(SIGALRM,(void (*)())timeout);
      alarm (r->server->timeout);
  }
  
--- 448,454 ----
      timeout_req = r;
      timeout_name = name;
      
!     signal(SIGALRM, timeout);
      alarm (r->server->timeout);
  }
  
***************
*** 439,445 ****
  {
      timeout_name = name;
      
!     signal(SIGALRM,(void (*)())timeout);
      alarm (r->server->timeout);
  }
  
--- 456,462 ----
  {
      timeout_name = name;
      
!     signal(SIGALRM, timeout);
      alarm (r->server->timeout);
  }
  
***************
*** 483,488 ****
--- 500,509 ----
   * calls to shutdown only half of the connection.  You should define
   * NO_LINGCLOSE in conf.h if such is the case for your system.
   */
+ #ifndef MAX_SECS_TO_LINGER
+ #define MAX_SECS_TO_LINGER 30
+ #endif
+ 
  #ifdef USE_SO_LINGER
  #define NO_LINGCLOSE    /* The two lingering options are exclusive */
  
***************
*** 491,497 ****
      struct linger li;
  
      li.l_onoff = 1;
!     li.l_linger = 30;
  
      if (setsockopt(s, SOL_SOCKET, SO_LINGER,
                     (char *)&li, sizeof(struct linger)) < 0) {
--- 512,518 ----
      struct linger li;
  
      li.l_onoff = 1;
!     li.l_linger = MAX_SECS_TO_LINGER;
  
      if (setsockopt(s, SOL_SOCKET, SO_LINGER,
                     (char *)&li, sizeof(struct linger)) < 0) {
***************
*** 523,539 ****
  	siglongjmp(jmpbuffer,1);
  #endif
      }
      current_conn->aborted = 1;
  }
      
  static void linger_timeout ()
  {
-     const int max_secs_to_linger = 30;
- 
      timeout_name = "lingering close";
      
!     signal(SIGALRM,(void (*)())lingerout);
!     alarm(max_secs_to_linger);
  }
  
  /* Since many clients will abort a connection instead of closing it,
--- 544,559 ----
  	siglongjmp(jmpbuffer,1);
  #endif
      }
+     bsetflag(current_conn->client, B_EOUT, 1);
      current_conn->aborted = 1;
  }
      
  static void linger_timeout ()
  {
      timeout_name = "lingering close";
      
!     signal(SIGALRM, lingerout);
!     alarm(MAX_SECS_TO_LINGER);
  }
  
  /* Since many clients will abort a connection instead of closing it,
***************
*** 556,562 ****
  
      /* Send any leftover data to the client, but never try to again */
  
!     bflush(r->connection->client);
      bsetflag(r->connection->client, B_EOUT, 1);
  
      /* Close our half of the connection --- send the client a FIN */
--- 576,586 ----
  
      /* Send any leftover data to the client, but never try to again */
  
!     if (bflush(r->connection->client) == -1) {
!         kill_timeout(r);
!         bclose(r->connection->client);
!         return;
!     }
      bsetflag(r->connection->client, B_EOUT, 1);
  
      /* Close our half of the connection --- send the client a FIN */
***************
*** 1435,1441 ****
  {
  #ifndef NO_USE_SIGACTION
      struct sigaction sa;
!     memset(&sa,0,sizeof sa);
  
      if (!one_process) {
  	sa.sa_handler = (void (*)())seg_fault;
--- 1459,1467 ----
  {
  #ifndef NO_USE_SIGACTION
      struct sigaction sa;
! 
!     sigemptyset(&sa.sa_mask);
!     sa.sa_flags = 0;
  
      if (!one_process) {
  	sa.sa_handler = (void (*)())seg_fault;
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.114
diff -c -r1.114 http_protocol.c
*** http_protocol.c	1997/04/20 04:02:08	1.114
--- http_protocol.c	1997/04/20 11:21:28
***************
*** 1252,1259 ****
  {
      /* Turn off chunked encoding */
  
!     if (r->chunked) {
!         hard_timeout("send ending chunk", r);
          bsetflag(r->connection->client, B_CHUNK, 0);
  	bputs("0\015\012", r->connection->client);
  	/* If we had footer "headers", we'd send them now */
--- 1252,1259 ----
  {
      /* Turn off chunked encoding */
  
!     if (r->chunked && !r->connection->aborted) {
!         soft_timeout("send ending chunk", r);
          bsetflag(r->connection->client, B_CHUNK, 0);
  	bputs("0\015\012", r->connection->client);
  	/* If we had footer "headers", we'd send them now */
***************
*** 1519,1525 ****
      char buf[IOBUFSIZE];
      long total_bytes_sent = 0;
      register int n, w, o, len;
-     conn_rec *c = r->connection;
      
      if (length == 0) return 0;
  
--- 1519,1524 ----
***************
*** 1531,1537 ****
  	else len = IOBUFSIZE;
  
          while ((n= fread(buf, sizeof(char), len, f)) < 1
! 	       && ferror(f) && errno == EINTR)
  	    continue;
  	
  	if (n < 1) {
--- 1530,1536 ----
  	else len = IOBUFSIZE;
  
          while ((n= fread(buf, sizeof(char), len, f)) < 1
! 	       && ferror(f) && errno == EINTR && !r->connection->aborted)
  	    continue;
  	
  	if (n < 1) {
***************
*** 1541,1547 ****
  	total_bytes_sent += n;
  	
          while(n && !r->connection->aborted) {
!             w=bwrite(c->client, &buf[o], n);
  	    if(w <= 0)
  		break;
  	    reset_timeout(r); /* reset timeout after successful write */
--- 1540,1546 ----
  	total_bytes_sent += n;
  	
          while(n && !r->connection->aborted) {
!             w=bwrite(r->connection->client, &buf[o], n);
  	    if(w <= 0)
  		break;
  	    reset_timeout(r); /* reset timeout after successful write */
Index: mod_cgi.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
retrieving revision 1.38
diff -c -r1.38 mod_cgi.c
*** mod_cgi.c	1997/04/16 19:49:59	1.38
--- mod_cgi.c	1997/04/20 11:21:28
***************
*** 459,466 ****
  		dbpos += dbsize;
  	    }
  	    reset_timeout(r);
! 	    if (fwrite(argsbuffer, 1, len_read, script_out) < (size_t)len_read) {
! 		/* silly script stopped reading, soak up remaining message */
  	        while (get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
  	            ; /* dump it */
  	        break;
--- 459,467 ----
  		dbpos += dbsize;
  	    }
  	    reset_timeout(r);
! 	    if (fwrite(argsbuffer, sizeof(char), len_read, script_out)
! 	            < (size_t)len_read) {
! 	        /* silly script stopped reading, soak up remaining message */
  	        while (get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
  	            ; /* dump it */
  	        break;
***************
*** 489,498 ****
  	  
  	    /* Soak up all the script output */
  	    hard_timeout ("read from script", r);
! 	    while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in) != NULL)
  	        continue;
- 	    while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_err) != NULL)
- 	      continue;
  	    kill_timeout (r);
  
  
--- 490,501 ----
  	  
  	    /* Soak up all the script output */
  	    hard_timeout ("read from script", r);
! 	    while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_in)
! 	           > 0)
! 	        continue;
! 	    while (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err)
! 	           > 0)
  	        continue;
  	    kill_timeout (r);
  
  
***************
*** 525,532 ****
  
  	/* Soak up stderr */
  	soft_timeout("soaking script stderr", r);
! 	while ((fgets(argsbuffer, HUGE_STRING_LEN-1, script_err) != NULL) &&
! 	       !r->connection->aborted)
  	    continue;
  	kill_timeout(r);
  	pfclose (r->main ? r->main->pool : r->pool, script_err);
--- 528,535 ----
  
  	/* Soak up stderr */
  	soft_timeout("soaking script stderr", r);
! 	while (!r->connection->aborted &&
! 	  (fread(argsbuffer, sizeof(char), HUGE_STRING_LEN, script_err) > 0))
  	    continue;
  	kill_timeout(r);
  	pfclose (r->main ? r->main->pool : r->pool, script_err);

Mime
View raw message