Re: keepalive connections and exiting MPM processes

2007-11-15 Thread Jeff Trawick
On Nov 13, 2007 10:38 AM, Jeff Trawick [EMAIL PROTECTED] wrote:
 On Nov 13, 2007 8:57 AM, Plüm, Rüdiger, VF-Group
 [EMAIL PROTECTED] wrote:
 
 
   -Ursprüngliche Nachricht-
   Von: Jeff Trawick
   Gesendet: Dienstag, 13. November 2007 14:31
   An: dev@httpd.apache.org
   Betreff: keepalive connections and exiting MPM processes
 
  
  
   When the MPM process handling the connection is or will be exiting, we
   can incorrectly tell the client that the connection will be held open
   after the current request.  This can result in user intervention
   (retry the POST?) or failures for some requests sent subsequently on
   that connection.

 ...


   It isn't so clear how to handle the remaining window, in which the MPM
   process starts exiting while we send the response (and after we've
   already determined the keepalive setting).
  
   From ap_process_http_connection():
  
   if (r-status == HTTP_OK) {
   cs-state = CONN_STATE_HANDLER;
   ap_process_request(r);
   r = NULL;
   }
  
   if (c-keepalive != AP_CONN_KEEPALIVE || c-aborted)
   break;
  
   XXX
   We could skip checking for graceful exit here since
   it is checked
   as part of the keepalive determination, but the MPM process
   could remain active much longer than expected (maybe we just
   downloaded a very large file).
   XXX
  
   if (ap_graceful_stop_signalled())
   break;
  
   For the remaining timing window, I'm afraid that a vhost-specific
   setting is needed to control whether we respect the connection
   keepalive setting or the MPM state.   (The latter is apparently good
 
  I guess we can leave it as it is in this situation. Although we SHOULD
  send connection: close if want to close the connection it is no MUST
  (8.1.2.1, last sentence first paragraph). And for pipelined requests the
  client must be prepared to resend anyway if we do not process all pipelined
  requests (8.1.2.2).

 Apart from the SHOULD vs. MUST is the end-user issue when the client
 software can't or won't retry automatically when confronted with a
 validly-dropped connection ;)

Here's a patch to address that issue:
http://people.apache.org/~trawick/keepalive.txt
(KeepAliveWhileExiting On|Off, default Off)

It comes down to this check in ap_process_http_connection():

while ((r = ap_read_request(c)) != NULL) {
...

if (c-keepalive != AP_CONN_KEEPALIVE || c-aborted)
break;

...

if (!c-base_server-keep_alive_while_exiting 
ap_graceful_stop_signalled())
break;

}

The only commentary I've seen on the general idea so far is that the
RFC doesn't force us to respect that persistence.


keepalive connections and exiting MPM processes

2007-11-13 Thread Jeff Trawick
When the MPM process handling the connection is or will be exiting, we
can incorrectly tell the client that the connection will be held open
after the current request.  This can result in user intervention
(retry the POST?) or failures for some requests sent subsequently on
that connection.

The case where we already know we're exiting at the time we determine
the keep-alive setting is simple to handle:

Index: modules/http/http_protocol.c
===
--- modules/http/http_protocol.c(revision 593813)
+++ modules/http/http_protocol.c(working copy)
@@ -48,6 +48,7 @@
 #include util_charset.h
 #include util_ebcdic.h
 #include util_time.h
+#include ap_mpm.h

 #include mod_core.h

@@ -187,6 +188,7 @@
  *   or they're a buggy twit coming through a HTTP/1.1 proxy
  *   andthe client is requesting an HTTP/1.0-style keep-alive
  *   or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
+ *   and this MPM process is not already exiting
  *   THEN we can be persistent, which requires more headers be output.
  *
  * Note that the condition evaluation order is extremely important.
@@ -212,7 +214,8 @@
  (!apr_table_get(r-subprocess_env, nokeepalive)
 || apr_table_get(r-headers_in, Via))
  ((ka_sent = ap_find_token(r-pool, conn, keep-alive))
-|| (r-proto_num = HTTP_VERSION(1,1 {
+|| (r-proto_num = HTTP_VERSION(1,1)))
+ !ap_graceful_stop_signalled()) {
 int left = r-server-keep_alive_max - r-connection-keepalives;

 r-connection-keepalive = AP_CONN_KEEPALIVE;

It isn't so clear how to handle the remaining window, in which the MPM
process starts exiting while we send the response (and after we've
already determined the keepalive setting).

From ap_process_http_connection():

if (r-status == HTTP_OK) {
cs-state = CONN_STATE_HANDLER;
ap_process_request(r);
r = NULL;
}

if (c-keepalive != AP_CONN_KEEPALIVE || c-aborted)
break;

XXX
We could skip checking for graceful exit here since it is checked
as part of the keepalive determination, but the MPM process
could remain active much longer than expected (maybe we just
downloaded a very large file).
XXX

if (ap_graceful_stop_signalled())
break;

For the remaining timing window, I'm afraid that a vhost-specific
setting is needed to control whether we respect the connection
keepalive setting or the MPM state.   (The latter is apparently good
enough for most folks, and it does avoid unexpected delays in child
processes exiting and switching to new configs.)

Thoughts?


Re: keepalive connections and exiting MPM processes

2007-11-13 Thread Plüm , Rüdiger , VF-Group


 -Ursprüngliche Nachricht-
 Von: Jeff Trawick 
 Gesendet: Dienstag, 13. November 2007 14:31
 An: dev@httpd.apache.org
 Betreff: keepalive connections and exiting MPM processes
 
 
 When the MPM process handling the connection is or will be exiting, we
 can incorrectly tell the client that the connection will be held open
 after the current request.  This can result in user intervention
 (retry the POST?) or failures for some requests sent subsequently on
 that connection.
 
 The case where we already know we're exiting at the time we determine
 the keep-alive setting is simple to handle:
 
 Index: modules/http/http_protocol.c
 ===
 --- modules/http/http_protocol.c(revision 593813)
 +++ modules/http/http_protocol.c(working copy)
 @@ -48,6 +48,7 @@
  #include util_charset.h
  #include util_ebcdic.h
  #include util_time.h
 +#include ap_mpm.h
 
  #include mod_core.h
 
 @@ -187,6 +188,7 @@
   *   or they're a buggy twit coming through a HTTP/1.1 proxy
   *   andthe client is requesting an HTTP/1.0-style keep-alive
   *   or the client claims to be HTTP/1.1 compliant 
 (perhaps a proxy);
 + *   and this MPM process is not already exiting
   *   THEN we can be persistent, which requires more 
 headers be output.
   *
   * Note that the condition evaluation order is extremely 
 important.
 @@ -212,7 +214,8 @@
   (!apr_table_get(r-subprocess_env, nokeepalive)
  || apr_table_get(r-headers_in, Via))
   ((ka_sent = ap_find_token(r-pool, conn, keep-alive))
 -|| (r-proto_num = HTTP_VERSION(1,1 {
 +|| (r-proto_num = HTTP_VERSION(1,1)))
 + !ap_graceful_stop_signalled()) {
  int left = r-server-keep_alive_max - 
 r-connection-keepalives;
 
  r-connection-keepalive = AP_CONN_KEEPALIVE;

Looks like a reasonable patch.

 
 It isn't so clear how to handle the remaining window, in which the MPM
 process starts exiting while we send the response (and after we've
 already determined the keepalive setting).
 
 From ap_process_http_connection():
 
 if (r-status == HTTP_OK) {
 cs-state = CONN_STATE_HANDLER;
 ap_process_request(r);
 r = NULL;
 }
 
 if (c-keepalive != AP_CONN_KEEPALIVE || c-aborted)
 break;
 
 XXX
 We could skip checking for graceful exit here since 
 it is checked
 as part of the keepalive determination, but the MPM process
 could remain active much longer than expected (maybe we just
 downloaded a very large file).
 XXX
 
 if (ap_graceful_stop_signalled())
 break;
 
 For the remaining timing window, I'm afraid that a vhost-specific
 setting is needed to control whether we respect the connection
 keepalive setting or the MPM state.   (The latter is apparently good

I guess we can leave it as it is in this situation. Although we SHOULD
send connection: close if want to close the connection it is no MUST
(8.1.2.1, last sentence first paragraph). And for pipelined requests the
client must be prepared to resend anyway if we do not process all pipelined
requests (8.1.2.2).

Regards

Rüdiger




Re: keepalive connections and exiting MPM processes

2007-11-13 Thread Jim Jagielski


On Nov 13, 2007, at 8:30 AM, Jeff Trawick wrote:


When the MPM process handling the connection is or will be exiting, we
can incorrectly tell the client that the connection will be held open
after the current request.  This can result in user intervention
(retry the POST?) or failures for some requests sent subsequently on
that connection.

The case where we already know we're exiting at the time we determine
the keep-alive setting is simple to handle:

 #include mod_core.h

@@ -187,6 +188,7 @@
  *   or they're a buggy twit coming through a HTTP/1.1 proxy
  *   andthe client is requesting an HTTP/1.0-style keep-alive
  *   or the client claims to be HTTP/1.1 compliant  
(perhaps a proxy);

+ *   and this MPM process is not already exiting
  *   THEN we can be persistent, which requires more headers be  
output.

  *
  * Note that the condition evaluation order is extremely  
important.

@@ -212,7 +214,8 @@
  (!apr_table_get(r-subprocess_env, nokeepalive)
 || apr_table_get(r-headers_in, Via))
  ((ka_sent = ap_find_token(r-pool, conn, keep-alive))
-|| (r-proto_num = HTTP_VERSION(1,1 {
+|| (r-proto_num = HTTP_VERSION(1,1)))
+ !ap_graceful_stop_signalled()) {
 int left = r-server-keep_alive_max - r-connection- 
keepalives;


 r-connection-keepalive = AP_CONN_KEEPALIVE;



Concept-wise, this makes sense...
 


Re: keepalive connections and exiting MPM processes

2007-11-13 Thread Jeff Trawick
On Nov 13, 2007 8:57 AM, Plüm, Rüdiger, VF-Group
[EMAIL PROTECTED] wrote:


  -Ursprüngliche Nachricht-
  Von: Jeff Trawick
  Gesendet: Dienstag, 13. November 2007 14:31
  An: dev@httpd.apache.org
  Betreff: keepalive connections and exiting MPM processes

 
 
  When the MPM process handling the connection is or will be exiting, we
  can incorrectly tell the client that the connection will be held open
  after the current request.  This can result in user intervention
  (retry the POST?) or failures for some requests sent subsequently on
  that connection.

...

  It isn't so clear how to handle the remaining window, in which the MPM
  process starts exiting while we send the response (and after we've
  already determined the keepalive setting).
 
  From ap_process_http_connection():
 
  if (r-status == HTTP_OK) {
  cs-state = CONN_STATE_HANDLER;
  ap_process_request(r);
  r = NULL;
  }
 
  if (c-keepalive != AP_CONN_KEEPALIVE || c-aborted)
  break;
 
  XXX
  We could skip checking for graceful exit here since
  it is checked
  as part of the keepalive determination, but the MPM process
  could remain active much longer than expected (maybe we just
  downloaded a very large file).
  XXX
 
  if (ap_graceful_stop_signalled())
  break;
 
  For the remaining timing window, I'm afraid that a vhost-specific
  setting is needed to control whether we respect the connection
  keepalive setting or the MPM state.   (The latter is apparently good

 I guess we can leave it as it is in this situation. Although we SHOULD
 send connection: close if want to close the connection it is no MUST
 (8.1.2.1, last sentence first paragraph). And for pipelined requests the
 client must be prepared to resend anyway if we do not process all pipelined
 requests (8.1.2.2).

Apart from the SHOULD vs. MUST is the end-user issue when the client
software can't or won't retry automatically when confronted with a
validly-dropped connection ;)


Re: keepalive connections and exiting MPM processes

2007-11-13 Thread Akins, Brian
On 11/13/07 8:30 AM, Jeff Trawick [EMAIL PROTECTED] wrote:


   * Note that the condition evaluation order is extremely important.
 @@ -212,7 +214,8 @@
   (!apr_table_get(r-subprocess_env, nokeepalive)
  || apr_table_get(r-headers_in, Via))
   ((ka_sent = ap_find_token(r-pool, conn, keep-alive))
 -|| (r-proto_num = HTTP_VERSION(1,1 {
 +|| (r-proto_num = HTTP_VERSION(1,1)))
 + !ap_graceful_stop_signalled()) {
  int left = r-server-keep_alive_max - r-connection-keepalives;
 
  r-connection-keepalive = AP_CONN_KEEPALIVE;

Looks reasonable.

We do so many checks in this function, and it's a pain to modify.  I wish
this were a hook.  I have selfish reasons for this, as I want an easy way to
limit the number of keepalives per child (especially in event mpm).  It
would be so much easier if this were a hook:

In event somewhere:

 static can_http_keepalive(request_rec *r) {
if (current_num_of_keepalives + 1  configured_max) {
return NO; /*whatever, not OK or declined...*/
}
return OK;
 }

When resources get tight, I'd like to disable keepalives so I don't have all
the freeloading connections hanging around.  (Sometimes every little bit
helps...)

Also, shouldn't Keepalive become HTTPKeepalive and live in the http_module's
config (which doesn't exist, I don't think) rather than is global
server_rec.  Keepalive doesn't make sense for mod_ftp, mod_dns, etc.

While I'm thinking about this, shouldn't virtual server selection be a hook
rather than the current core way... Would make eventually dynamic
server_rec creation easier.


  
-- 
Brian Akins
Chief Operations Engineer
Turner Digital Media Technologies