You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ed Korthof <ed...@organic.com> on 1997/01/20 13:07:40 UTC

Patch for new Timeouts

This is a bit more complete than the previous patch I sent; it
incorporates the features discussed on the list (at least, those I could
find).  I'll send a patch for the documentation tomorrow -- but basically
this allows for timeout for reading the headers, for reading a
(presumably, POSTed) message body, and a per-chunk timeout.  All are
configured through 'Timeout [type] #'.

All of the new timeouts default to zero, which disables them, so this will
behave exactly like the current version unless configured otherwise. 

This could be usefully generalized by forming a table of Timeouts by name
and value, and looking up against that; but I was worried about
efficiency.  Still, if others here would prefer such a system, it'd be
easy to rewrite this (now that I've got a handle on the TAKE12 method). 
Also, there's one timeout which is currently unused -- Timeout Read # --
I'd like to write code to have a static counter for the entire time spent
reading the request, so as to provide for an absolute maximum to the time
spent reading the request.

While looking this over, I believe I found a bug in the RLimit* code -- it
doesn't appear to notice a second argument (basically, the set_rlimit &
etc. functions need to be given another argument for another char *
(possibly NULL)).  Anyway, I'll post a patch to that tomorrow (too tired
right now).

     -- Ed Korthof        |  Web Server Engineer --
     -- ed@organic.com    |  Organic Online, Inc --
     -- (415) 278-5676    |  Fax: (415) 284-6891 --

*** /usr/local/src/apache/apache_1.2b2/src/http_main.c	Sat Jan 18 15:07:44 1997
--- http_main.c	Mon Jan 20 03:41:02 1997
***************
*** 461,466 ****
--- 461,474 ----
      signal(SIGALRM,(void (*)())timeout);
      if (r->connection->keptalive) 
         alarm (r->server->keep_alive_timeout);
+     else if (r->server->timeout_read && !strcmp(name, "Read"))
+        alarm (r->server->timeout_read);
+     else if (r->server->timeout_read_per_chunk && !strcmp(name, "ReadPerChunk"))
+        alarm (r->server->timeout_read_per_chunk);
+     else if (r->server->timeout_read_header && !strcmp(name, "ReadHeader"))
+        alarm (r->server->timeout_read_header);
+     else if (r->server->timeout_read_content && !strcmp(name, "ReadContent"))
+        alarm (r->server->timeout_read_content);
      else
         alarm (r->server->timeout);
  }
*** /usr/local/src/apache/apache_1.2b2/src/http_core.c	Sat Jan 18 15:07:43 1997
--- http_core.c	Mon Jan 20 03:26:15 1997
***************
*** 879,886 ****
      return NULL;
  }
  
! const char *set_timeout (cmd_parms *cmd, void *dummy, char *arg) {
!     cmd->server->timeout = atoi (arg);
      return NULL;
  }
  
--- 879,916 ----
      return NULL;
  }
  
! const char *set_timeout (cmd_parms *cmd, void *dummy, const char *arg, const char *arg2) {
!     int  * target = 0;
!     char * str;
!     if ((str = getword_conf(cmd->pool, &arg))) {
!         if (!strncmp(str,"Read",4)) {
!             if (!strcmp(str, "Read")) {
!                 target = & cmd->server->timeout_read;
!             } else if (!strcmp(str, "ReadPerChunk")) {
!                 target = & cmd->server->timeout_read_per_chunk;
!             } else if (!strcmp(str, "ReadHeader")) {
!                 target = & cmd->server->timeout_read_header;
!             } else if (!strcmp(str, "ReadContent")) {
!                 target = & cmd->server->timeout_read_content;
!             } else {
! 	        log_printf(cmd->server, "Invalid parameters for %s", cmd->cmd->name);
! 	        return NULL;
!             }
!         }
!         else {
! 	    cmd->server->timeout = atoi(str);
!         }
!     }
!     else {
!         log_printf(cmd->server, "Invalid parameters for %s", cmd->cmd->name);
!         return NULL;
!     }
!     
!     if (target && (str = getword_conf(cmd->pool, &arg2))) {
! 	*target = atoi(str);
!     } else if (target) {
!         log_printf(cmd->server, "Invalid parameters for %s", cmd->cmd->name);
!     }
      return NULL;
  }
  
***************
*** 1160,1166 ****
     "A name or names alternately used to access the server" },
  { "ServerPath", set_serverpath, NULL, RSRC_CONF, TAKE1,
    "The pathname the server can be reached at" },
! { "Timeout", set_timeout, NULL, RSRC_CONF, TAKE1, "Timeout duration (sec)"},
  { "KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF, TAKE1, "Keep-Alive timeout duration (sec)"},
  { "KeepAlive", set_keep_alive, NULL, RSRC_CONF, TAKE1, "Maximum Keep-Alive requests per connection (0 to disable)" },
  { "IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF, FLAG, "Enable identd (RFC931) user lookups - SLOW" },
--- 1190,1196 ----
     "A name or names alternately used to access the server" },
  { "ServerPath", set_serverpath, NULL, RSRC_CONF, TAKE1,
    "The pathname the server can be reached at" },
! { "Timeout", set_timeout, (void *)NULL, OR_ALL, TAKE12, "Timeout duration (sec), takes one or two arguments: with 1, sets default timeout; with 2, 1st is name of the timeout to set.  Options are: Read, ReadPerChunk, ReadHeader, ReadContent"},
  { "KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF, TAKE1, "Keep-Alive timeout duration (sec)"},
  { "KeepAlive", set_keep_alive, NULL, RSRC_CONF, TAKE1, "Maximum Keep-Alive requests per connection (0 to disable)" },
  { "IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF, FLAG, "Enable identd (RFC931) user lookups - SLOW" },
*** /usr/local/src/apache/apache_1.2b2/src/http_config.c	Sat Jan 18 15:07:43 1997
--- http_config.c	Mon Jan 20 03:24:12 1997
***************
*** 914,919 ****
--- 914,923 ----
      s->srm_confname = NULL;
      s->access_confname = NULL;
      s->timeout = 0;
+     s->timeout_read = 0;
+     s->timeout_read_per_chunk = 0;
+     s->timeout_read_header = 0;
+     s->timeout_read_content = 0;
      s->keep_alive_timeout = 0;
      s->keep_alive = -1;
      /* start the list of addreses */
***************
*** 1019,1024 ****
--- 1023,1032 ----
      s->srm_confname = RESOURCE_CONFIG_FILE;
      s->access_confname = ACCESS_CONFIG_FILE;
      s->timeout = DEFAULT_TIMEOUT;
+     s->timeout_read = DEFAULT_TIMEOUT_READ;
+     s->timeout_read_per_chunk = DEFAULT_TIMEOUT_READ_PER_CHUNK;
+     s->timeout_read_header = DEFAULT_TIMEOUT_READ_HEADER;
+     s->timeout_read_content = DEFAULT_TIMEOUT_READ_CONTENT;
      s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
      s->keep_alive = DEFAULT_KEEPALIVE;
      s->next = NULL;
*** /usr/local/src/apache/apache_1.2b2/src/httpd.h	Sat Jan 18 15:07:43 1997
--- httpd.h	Mon Jan 20 03:28:13 1997
***************
*** 183,188 ****
--- 183,197 ----
  /* The timeout for waiting for messages */
  #define DEFAULT_TIMEOUT 1200
  
+ /* The timeout to read a request */
+ #define DEFAULT_TIMEOUT_READ 180
+ 
+ /* Timeouts per chunk, and to apply after we realize that incoming message
+ has a message body.  Defaults are set to 0 to disable. */
+ #define DEFAULT_TIMEOUT_READ_PER_CHUNK 0
+ #define DEFAULT_TIMEOUT_READ_HEADER 0
+ #define DEFAULT_TIMEOUT_READ_CONTENT 0
+ 
  /* The timeout for waiting for keepalive timeout until next request */
  #define DEFAULT_KEEPALIVE_TIMEOUT 15
  
***************
*** 585,590 ****
--- 594,604 ----
  
      server_addr_rec *addrs;
      int timeout;		/* Timeout, in seconds, before we give up */
+     int timeout_read;		/* Timeout, in seconds, to read request */
+     int timeout_read_per_chunk; /* Timeout, in seconds, between reads */
+     int timeout_read_header;    /* Timeout, in seconds, for reading the header*/
+     int timeout_read_content;   /* Timeout, in seconds, to read a request */
+                                 /* w/ content -- eg. a POST */
      int keep_alive_timeout;	/* Seconds we'll wait for another request */
      int keep_alive;		/* Maximum requests per connection */
      int send_buffer_size;       /* size of TCP send buffer (in bytes) */
*** /usr/local/src/apache/apache_1.2b2/src/http_protocol.c	Mon Jan  6 18:17:53 1997
--- http_protocol.c	Mon Jan 20 02:14:11 1997
***************
*** 652,661 ****
  
      /* Get the request... */
      
!     hard_timeout ("read", r);
      if (!read_request_line (r)) return NULL;
      if (!r->assbackwards) get_mime_headers (r);
  
  /* handle Host header here, to get virtual server */
  
      if (r->hostname || (r->hostname = table_get(r->headers_in, "Host")))
--- 652,664 ----
  
      /* Get the request... */
      
!     hard_timeout ("ReadHeader", r);
! 
      if (!read_request_line (r)) return NULL;
      if (!r->assbackwards) get_mime_headers (r);
  
+     kill_timeout (r);
+ 
  /* handle Host header here, to get virtual server */
  
      if (r->hostname || (r->hostname = table_get(r->headers_in, "Host")))
***************
*** 663,669 ****
      else
        check_serverpath(r);
  
-     kill_timeout (r);
      conn->keptalive = 0;   /* We now have a request - so no more short timeouts */
      
      if(!strcmp(r->method, "HEAD")) {
--- 666,671 ----
***************
*** 1227,1233 ****
      if (bufsiz <= 0)
          return -1;             /* Cannot read chunked with a small buffer */
  
!     if (r->remaining == 0) {         /* Start of new chunk */
  
          chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
          if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
--- 1229,1236 ----
      if (bufsiz <= 0)
          return -1;             /* Cannot read chunked with a small buffer */
  
!     if (r->remaining == 0) {             /* Start of new chunk */
!         hard_timeout("ReadPerChunk", r); /* Timeout for reading a chunk */
  
          chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
          if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
*** /usr/local/src/apache/apache_1.2b2/src/mod_cgi.c	Sun Dec  1 12:28:55 1996
--- mod_cgi.c	Mon Jan 20 03:56:19 1997
***************
*** 419,425 ****
  	    dbpos = 0;
  	}
  
!         hard_timeout ("copy script args", r);
          handler = signal (SIGPIPE, SIG_IGN);
      
  	while ((len_read =
--- 419,425 ----
  	    dbpos = 0;
  	}
  
!         hard_timeout ("ReadContent", r);
          handler = signal (SIGPIPE, SIG_IGN);
      
  	while ((len_read =