Upstream keepalive: keepalive_timeout directive.

The directive configures maximum time a connection can be kept in the
cache.  By configuring a time which is smaller than the corresponding
timeout on the backend side one can avoid the race between closing
a connection by the backend and nginx trying to use the same connection
to send a request at the same time.
diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c
index ef21ea2..ffb2bcf 100644
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
@@ -12,6 +12,7 @@
 
 typedef struct {
     ngx_uint_t                         max_cached;
+    ngx_msec_t                         timeout;
 
     ngx_queue_t                        cache;
     ngx_queue_t                        free;
@@ -84,6 +85,13 @@
       0,
       NULL },
 
+    { ngx_string("keepalive_timeout"),
+      NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_msec_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_upstream_keepalive_srv_conf_t, timeout),
+      NULL },
+
       ngx_null_command
 };
 
@@ -133,6 +141,8 @@
     kcf = ngx_http_conf_upstream_srv_conf(us,
                                           ngx_http_upstream_keepalive_module);
 
+    ngx_conf_init_msec_value(kcf->timeout, 60000);
+
     if (kcf->original_init_upstream(cf, us) != NGX_OK) {
         return NGX_ERROR;
     }
@@ -261,6 +271,10 @@
     c->write->log = pc->log;
     c->pool->log = pc->log;
 
+    if (c->read->timer_set) {
+        ngx_del_timer(c->read);
+    }
+
     pc->connection = c;
     pc->cached = 1;
 
@@ -339,10 +353,9 @@
 
     pc->connection = NULL;
 
-    if (c->read->timer_set) {
-        c->read->delayed = 0;
-        ngx_del_timer(c->read);
-    }
+    c->read->delayed = 0;
+    ngx_add_timer(c->read, kp->conf->timeout);
+
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
     }
@@ -393,7 +406,7 @@
 
     c = ev->data;
 
-    if (c->close) {
+    if (c->close || c->read->timedout) {
         goto close;
     }
 
@@ -486,6 +499,8 @@
      *     conf->max_cached = 0;
      */
 
+    conf->timeout = NGX_CONF_UNSET_MSEC;
+
     return conf;
 }