Binary files Pound-1.9.5_ORIG/.svc.c.swp and Pound-1.9.5/.svc.c.swp differ
diff -ruN Pound-1.9.5_ORIG/config.c Pound-1.9.5/config.c
--- Pound-1.9.5_ORIG/config.c	2005-12-07 11:58:28.000000000 +0200
+++ Pound-1.9.5/config.c	2006-01-23 01:44:51.000000000 +0200
@@ -203,6 +203,15 @@
 #define SYSLOG_NAMES    1
 #endif
 
+#define INIT_BE(be, ADDR, ALIVE_ADDR) \
+                be.addr = ADDR; \
+                be.alive_addr = ALIVE_ADDR; \
+                be.alive = 1; \
+                be.degraded = 0; \
+                be.failed_alive_checks = 0; \
+                be.in_flight_reqs = 0; \
+                be.timeout = 0;
+
 #include    "pound.h"
 
 #ifdef MISS_FACILITYNAMES
@@ -279,7 +288,7 @@
                         SSL_Verifylist, User, Group, RootJail, ExtendedHTTP, WebDAV, LogFacility, LogLevel, Alive,
                         Server, Client, UrlGroup, HeadRequire, HeadDeny, BackEnd, BackEndHA, EndGroup,
                         Err500, Err501, Err503, Err414, CheckURL, CS_SEGMENT, CS_PARM, CS_QID, CS_QVAL, CS_FRAG,
-                        RewriteRedir, NoDaemon;
+                        RewriteRedir, NoDaemon, AliveChecks, ConTimeBeforeKill, InFlightReqs;
     regex_t             *req, *deny;
     regmatch_t          matches[5];
     struct sockaddr_in  addr, alive_addr;
@@ -339,6 +348,9 @@
     || regcomp(&MaxRequest, "^[ \t]*MaxRequest[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&RewriteRedir, "^[ \t]*RewriteRedirect[ \t]+([0-2])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&NoDaemon, "^[ \t]*NoDaemon[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+    || regcomp(&AliveChecks, "^[ \t]*alive_checks_before_kill[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+    || regcomp(&ConTimeBeforeKill, "^[ \t]*con_timeout_before_kill[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+    || regcomp(&InFlightReqs, "^[ \t]*in_flight_req_limit[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     ) {
         logmsg(LOG_ERR, "bad config Regex - aborted");
         exit(1);
@@ -576,6 +588,12 @@
             log_level = atoi(lin + matches[1].rm_so);
         } else if(!regexec(&Alive, lin, 4, matches, 0)) {
             alive_to = atoi(lin + matches[1].rm_so);
+        } else if(!regexec(&AliveChecks, lin, 4, matches, 0)) {
+            alive_checks_before_kill = atoi(lin + matches[1].rm_so);
+        } else if(!regexec(&ConTimeBeforeKill, lin, 4, matches, 0)) {
+            con_timeout_before_kill = atoi(lin + matches[1].rm_so);
+	} else if(!regexec(&InFlightReqs, lin, 4, matches, 0)) {
+            in_flight_req_limit = atoi(lin + matches[1].rm_so);
         } else if(!regexec(&Client, lin, 4, matches, 0)) {
             clnt_to = atoi(lin + matches[1].rm_so);
         } else if(!regexec(&Server, lin, 4, matches, 0)) {
@@ -621,9 +639,14 @@
             memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], sizeof(addr.sin_addr.s_addr));
             addr.sin_port = (in_port_t)htons(atoi(lin + matches[2].rm_so));
             for(k = atoi(lin + matches[3].rm_so); k > 0; k--, j++) {
-                be[j].addr = addr;
-                be[j].alive_addr = alive_addr;
-                be[j].alive = 1;
+		INIT_BE(be[j], addr, alive_addr)
+                // be[j].addr = addr;
+                // be[j].alive_addr = alive_addr;
+                // be[j].alive = 1;
+		// be[j].degraded = 0;
+		// be[j].failed_alive_checks = 0;
+		// be[j].in_flight_reqs = 0;
+		// be[j].timeout = 0;
             }
         } else if(in_group && !regexec(&BackEndHA, lin, 5, matches, 0)) {
             memset(&addr, 0, sizeof(addr));
@@ -640,9 +663,10 @@
             addr.sin_port = (in_port_t)htons(atoi(lin + matches[2].rm_so));
             alive_addr.sin_port = (in_port_t)htons(atoi(lin + matches[4].rm_so));
             for(k = atoi(lin + matches[3].rm_so); k > 0; k--, j++) {
-                be[j].addr = addr;
-                be[j].alive_addr = alive_addr;
-                be[j].alive = 1;
+		INIT_BE(be[j], addr, alive_addr)
+                // be[j].addr = addr;
+                // be[j].alive_addr = alive_addr;
+                // be[j].alive = 1;
             }
         } else if(in_group && !regexec(&SessionIP, lin, 4, matches, 0)) {
             if(groups[tot_groups]->sess_type != SessNONE) {
@@ -830,6 +854,9 @@
     allow_dav = 0;
     no_https_11 = 2;
     alive_to = 30;
+    alive_checks_before_kill = 5;
+    con_timeout_before_kill = 300;
+    in_flight_req_limit = 300;
     max_req = 0L;
     http = NULL;
     https = NULL;
diff -ruN Pound-1.9.5_ORIG/http.c Pound-1.9.5/http.c
--- Pound-1.9.5_ORIG/http.c	2005-12-07 11:58:28.000000000 +0200
+++ Pound-1.9.5/http.c	2006-01-23 03:37:21.000000000 +0200
@@ -600,6 +600,7 @@
     regmatch_t          matches[4];
     struct linger       l;
     GROUP               *grp;
+    BACKEND		*backend;
 
     a = (thr_arg *)arg;
     from_host = a->from_host;
@@ -836,17 +837,33 @@
         }
         while(be == NULL) {
             /* find the session - if any */
-            if((srv = get_be(grp = get_grp(url, &headers[1]), from_host, url, &headers[1])) == NULL) {
-				logmsg(LOG_WARNING, "no backend \"%s\" from %s", request, inet_ntoa(from_host));
+            if((backend = get_be(grp = get_grp(url, &headers[1]), from_host, url, &headers[1])) == NULL) {
+		logmsg(LOG_WARNING, "no backend \"%s\" from %s", request, inet_ntoa(from_host));
                 err_reply(cl, h503, e503);
                 free_headers(headers);
                 clean_all();
                 pthread_exit(NULL);
             }
+            srv = &backend->addr;
+            /* if be is degraded and has too many in-flight requests then just return right away */
+            if (backend->degraded) {
+                if (backend->in_flight_reqs > in_flight_req_limit) {
+                    logmsg(LOG_WARNING, "droping connection to %s because in_flight_req_limit reached (%d)",
+		    	inet_ntoa(srv->sin_addr), backend->in_flight_reqs);
+                    err_reply(cl, h503, e503);
+                    free_headers(headers);
+                    clean_all();
+                    pthread_exit(NULL);
+                } else {
+                    backend->in_flight_reqs++;
+                }
+            }
 
             if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
                 logmsg(LOG_WARNING, "backend %s:%hd create: %s",
                     inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                if (backend->in_flight_reqs > 0)
+                    backend->in_flight_reqs--;
                 err_reply(cl, h503, e503);
                 free_headers(headers);
                 clean_all();
@@ -856,8 +873,20 @@
                 logmsg(LOG_WARNING, "backend %s:%hd connect: %s",
                     inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
                 close(sock);
-                kill_be(srv);
-                continue;
+                if (backend->in_flight_reqs > 0)
+                    backend->in_flight_reqs--;
+		/* backend connection timed out! must downgrade backend life indicators a little */
+		timeout_be(srv);
+		err_reply(cl, h503, e503);
+		free_headers(headers);
+		clean_all();
+		pthread_exit(NULL);
+            }
+            if (backend->degraded) {
+                /* resurect backend if needed */
+                logmsg(LOG_ERR, "backend %s: killtimer cleared", inet_ntoa(srv->sin_addr));
+                backend->timeout = 0; 
+                backend->degraded = 0;
             }
             n = 1;
             setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&n, sizeof(n));
@@ -868,6 +897,8 @@
                 logmsg(LOG_WARNING, "BIO_new_socket server failed");
                 shutdown(sock, 2);
                 close(sock);
+                if (backend->in_flight_reqs > 0)
+                    backend->in_flight_reqs--;
                 free_headers(headers);
                 clean_all();
                 pthread_exit(NULL);
@@ -879,6 +910,8 @@
             }
             if((bb = BIO_new(BIO_f_buffer())) == NULL) {
                 logmsg(LOG_WARNING, "BIO_new(buffer) server failed");
+                if (backend->in_flight_reqs > 0)
+                    backend->in_flight_reqs--;
                 free_headers(headers);
                 clean_all();
                 pthread_exit(NULL);
@@ -895,6 +928,8 @@
             if(BIO_printf(be, "%s\r\n", headers[n]) <= 0) {
                 logmsg(LOG_WARNING, "error write to %s:%hd: %s",
                     inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                if (backend->in_flight_reqs > 0)
+                    backend->in_flight_reqs--;
                 err_reply(cl, h500, e500);
                 free_headers(headers);
                 clean_all();
@@ -911,6 +946,7 @@
                 if(BIO_printf(be, "%s\r\n", https_header) <= 0) {
                     logmsg(LOG_WARNING, "error write HTTPSHeader to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     clean_all();
                     pthread_exit(NULL);
@@ -921,6 +957,7 @@
                 if(BIO_printf(be, "X-SSL-Subject: %s\r\n", buf) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-Subject to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -932,6 +969,7 @@
                 if(BIO_printf(be, "X-SSL-Issuer: %s\r\n", buf) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-Issuer to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -943,6 +981,7 @@
                 if(BIO_printf(be, "X-SSL-notBefore: %s\r\n", buf) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-notBefore to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -954,6 +993,7 @@
                 if(BIO_printf(be, "X-SSL-notAfter: %s\r\n", buf) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-notAfter to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -962,6 +1002,7 @@
                 if(BIO_printf(be, "X-SSL-serial: %ld\r\n", ASN1_INTEGER_get(X509_get_serialNumber(x509))) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-serial to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -973,6 +1014,7 @@
                 if(BIO_printf(be, "X-SSL-certificate: %s\r\n", buf) <= 0) {
                     logmsg(LOG_WARNING, "error write X-SSL-certificate to %s:%hd: %s",
                         inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     err_reply(cl, h500, e500);
                     BIO_free_all(bb);
                     clean_all();
@@ -983,6 +1025,7 @@
                     if(BIO_printf(be, "\t%s\r\n", buf) <= 0) {
                         logmsg(LOG_WARNING, "error write X-SSL-certificate to %s:%hd: %s",
                             inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                        if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                         err_reply(cl, h500, e500);
                         BIO_free_all(bb);
                         clean_all();
@@ -995,6 +1038,7 @@
                     if(BIO_printf(be, "X-SSL-cipher: %s\r\n", buf) <= 0) {
                         logmsg(LOG_WARNING, "error write X-SSL-cipher to %s:%hd: %s",
                             inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                        if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                         err_reply(cl, h500, e500);
                         clean_all();
                         pthread_exit(NULL);
@@ -1012,6 +1056,7 @@
         if(cl_11 && chunked) {
             /* had Transfer-encoding: chunked so read/write all the chunks (HTTP/1.1 only) */
             if(copy_chunks(cl, be, NULL, 0, max_req)) {
+                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                 err_reply(cl, h500, e500);
                 clean_all();
                 pthread_exit(NULL);
@@ -1020,6 +1065,7 @@
             /* had Content-length, so do raw reads/writes for the length */
             if(copy_bin(cl, be, cont, NULL, 0)) {
                 logmsg(LOG_WARNING, "error copy client cont: %s", strerror(errno));
+                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                 err_reply(cl, h500, e500);
                 clean_all();
                 pthread_exit(NULL);
@@ -1030,6 +1076,7 @@
         if(BIO_flush(be) != 1) {
             logmsg(LOG_WARNING, "error flush to %s:%hd: %s",
                 inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+            if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
             err_reply(cl, h500, e500);
             clean_all();
             pthread_exit(NULL);
@@ -1058,6 +1105,7 @@
             if((headers = get_headers(be, cl)) == NULL) {
                 logmsg(LOG_WARNING, "response error read from %s:%hd: %s",
                     inet_ntoa(srv->sin_addr), ntohs(srv->sin_port), strerror(errno));
+                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                 err_reply(cl, h500, e500);
                 clean_all();
                 pthread_exit(NULL);
@@ -1095,6 +1143,7 @@
                         free(headers[n]);
                         if((headers[n] = strdup(buf)) == NULL) {
                             logmsg(LOG_WARNING, "rewrite Location - out of memory: %s", strerror(errno));
+                            if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                             free_headers(headers);
                             clean_all();
                             pthread_exit(NULL);
@@ -1113,6 +1162,7 @@
                     if(BIO_printf(cl, "%s\r\n", headers[n]) <= 0) {
                         if(errno)
                             logmsg(LOG_WARNING, "error write to %s: %s", inet_ntoa(from_host), strerror(errno));
+                        if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                         free_headers(headers);
                         clean_all();
                         pthread_exit(NULL);
@@ -1126,6 +1176,7 @@
             if(BIO_flush(cl) != 1) {
                 if(errno)
                     logmsg(LOG_WARNING, "error flush headers to %s: %s", inet_ntoa(from_host), strerror(errno));
+                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                 clean_all();
                 pthread_exit(NULL);
             }
@@ -1136,6 +1187,7 @@
                     /* had Transfer-encoding: chunked so read/write all the chunks (HTTP/1.1 only) */
                     if(copy_chunks(be, cl, &res_bytes, skip, 0L)) {
                         /* copy_chunks() has its own error messages */
+                        if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                         clean_all();
                         pthread_exit(NULL);
                     }
@@ -1144,6 +1196,7 @@
                     if(copy_bin(be, cl, cont, &res_bytes, skip)) {
                         if(errno)
                             logmsg(LOG_WARNING, "error copy server cont: %s", strerror(errno));
+                        if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                         clean_all();
                         pthread_exit(NULL);
                     }
@@ -1163,12 +1216,14 @@
                         while(BIO_pending(be)) {
                             if(BIO_read(be, &one, 1) != 1) {
                                 logmsg(LOG_WARNING, "error read response pending: %s", strerror(errno));
+                                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                                 clean_all();
                                 pthread_exit(NULL);
                             }
                             if(BIO_write(cl, &one, 1) != 1) {
                                 if(errno)
                                     logmsg(LOG_WARNING, "error write response pending: %s", strerror(errno));
+                                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                                 clean_all();
                                 pthread_exit(NULL);
                             }
@@ -1181,6 +1236,7 @@
                          */
                         if((be_unbuf = BIO_find_type(be, BIO_TYPE_SOCKET)) == NULL) {
                             logmsg(LOG_WARNING, "error get unbuffered: %s", strerror(errno));
+                            if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                             clean_all();
                             pthread_exit(NULL);
                         }
@@ -1192,6 +1248,7 @@
                             if(BIO_write(cl, buf, res) != res) {
                                 if(errno)
                                     logmsg(LOG_WARNING, "error copy response body: %s", strerror(errno));
+                                if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                                 clean_all();
                                 pthread_exit(NULL);
                             } else {
@@ -1204,6 +1261,7 @@
                 if(BIO_flush(cl) != 1) {
                     if(errno)
                         logmsg(LOG_WARNING, "error final flush to %s: %s", inet_ntoa(from_host), strerror(errno));
+                    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
                     clean_all();
                     pthread_exit(NULL);
                 }
@@ -1263,6 +1321,7 @@
     if(ssl != NULL)
         SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
 
+    if (backend->in_flight_reqs > 0) backend->in_flight_reqs--;
     clean_all();
     pthread_exit(NULL);
 }
diff -ruN Pound-1.9.5_ORIG/pound.c Pound-1.9.5/pound.c
--- Pound-1.9.5_ORIG/pound.c	2005-12-07 11:58:28.000000000 +0200
+++ Pound-1.9.5/pound.c	2006-01-23 01:55:42.000000000 +0200
@@ -235,6 +235,9 @@
 int     no_https_11;        /* disallow HTTP/1.1 clients for SSL connections */
 int     alive_to;           /* check interval for resurrection */
 long    max_req;            /* maximal allowed request size */
+int	alive_checks_before_kill; /* how many times must periodic check fail before host is killed */
+int	con_timeout_before_kill; /* how much time must pass from first timed out connection without successfull ones, before we kill backend */
+int	in_flight_req_limit; /* how many requests can degraded host have open at once */
 char    **http,             /* HTTP port to listen on */
         **https,            /* HTTPS port to listen on */
         **cert,             /* certificate file */
diff -ruN Pound-1.9.5_ORIG/pound.h Pound-1.9.5/pound.h
--- Pound-1.9.5_ORIG/pound.h	2005-12-07 11:58:28.000000000 +0200
+++ Pound-1.9.5/pound.h	2006-01-20 06:03:27.000000000 +0200
@@ -281,6 +281,9 @@
 extern int  allow_dav;          /* allow WebDAV - LOCK, UNLOCK */
 extern int  no_https_11;        /* disallow HTTP/1.1 clients for SSL connections */
 extern int  alive_to;           /* check interval for resurrection */
+extern int  alive_checks_before_kill; /* how many times must periodic check fail before host is killed */
+extern int  con_timeout_before_kill; /* how much time must pass from first timed out connection without successfull ones, before we kill backend */
+extern int  in_flight_req_limit; /* how many requests can degraded host have open at once */
 extern long max_req;            /* maximal allowed request size */
 extern char **http,             /* HTTP port to listen on */
             **https,            /* HTTPS port to listen on */
@@ -327,6 +330,10 @@
     struct sockaddr_in  addr;       /* address */
     struct sockaddr_in  alive_addr; /* address for viability port */
     int                 alive;      /* alive check interval */
+    int			degraded;   /* dont put any new sessions there */
+    int			failed_alive_checks; /* how many alive checks have failed in a row */
+    time_t		timeout;    /* when backend started to time out connections */
+    int			in_flight_reqs;
 }   BACKEND;
 
 /* session key max size */
@@ -431,7 +438,7 @@
 /*
  * Find the host to connect to
  */
-extern struct sockaddr_in *get_be(GROUP *, struct in_addr, char *, char **);
+extern BACKEND *get_be(GROUP *, struct in_addr, char *, char **);
 
 /*
  * (for cookies only) possibly create session based on response headers
diff -ruN Pound-1.9.5_ORIG/svc.c Pound-1.9.5/svc.c
--- Pound-1.9.5_ORIG/svc.c	2005-12-07 11:58:28.000000000 +0200
+++ Pound-1.9.5/svc.c	2006-02-17 15:42:12.000000000 +0200
@@ -528,10 +528,10 @@
 /*
  * Find the host to connect to
  */
-struct sockaddr_in *
+BACKEND *
 get_be(GROUP *g, struct in_addr from_host, char *url, char **headers)
 {
-    struct sockaddr_in  *res;
+    BACKEND  *res;
     SESS                *sp;
     int                 n, orig;
     char                *key;
@@ -547,24 +547,25 @@
     key = get_key(g, from_host, url, headers);
     if(key != NULL && g->sess_to > 0) {
         /* check for session, add it if necessary */
-        if((sp = sess_find(g->sessions, key)) == NULL) {
+	sp = sess_find(g->sessions, key);
+        if(sp == NULL || !strncmp(key, "NONE", 4)) {
             /* no session yet - create one */
             orig = n = rand() % g->tot_pri;
-            while(!g->backend_addr[n].alive) {
+            while(!g->backend_addr[n].alive || g->backend_addr[n].degraded)  {
                 n = (n + 1) % g->tot_pri;
                 if(n == orig)
                     break;
             }
-            if(g->backend_addr[n].alive) {
+            if(g->backend_addr[n].alive && !g->backend_addr[n].degraded) {
                 g->sessions = sess_add(g->sessions, key, n);
-                res = &(g->backend_addr[n].addr);
+                res = &(g->backend_addr[n]);
             } else
                 res = NULL;
         } else {
             /* session found */
             if(g->backend_addr[sp->to_host].alive) {
                 sp->last_acc = time(NULL);
-                res = &(g->backend_addr[sp->to_host].addr);
+                res = &(g->backend_addr[sp->to_host]);
             } else
                 res = NULL;
         }
@@ -584,13 +585,13 @@
             /* just choose a random backend */
             orig = n = rand() % g->tot_pri;
         }
-        while(!g->backend_addr[n].alive) {
+        while(!g->backend_addr[n].alive || g->backend_addr[n].degraded) {
             n = (n + 1) % g->tot_pri;
             if(n == orig)
                 break;
         }
-        if(g->backend_addr[n].alive)
-            res = &(g->backend_addr[n].addr);
+        if(g->backend_addr[n].alive && !g->backend_addr[n].degraded)
+            res = &(g->backend_addr[n]);
         else
             res = NULL;
     }
@@ -650,10 +651,78 @@
         for(i = 0; i < g->tot_pri; i++)
             if(memcmp(&(g->backend_addr[i].addr), be, sizeof(*be)) == 0) {
                 g->backend_addr[i].alive = 0;
+                g->backend_addr[i].degraded = 0;
                 g->sessions = sess_dead(g->sessions, i);
             }
         pthread_mutex_unlock(&g->mut);
     }
+    logmsg(LOG_ERR,"BackEnd %s is dead", inet_ntoa(be->sin_addr));
+    return;
+}
+
+/*
+ * mark a backend host as dead;
+ * do nothing if no resurection code is active
+ */
+void
+timeout_be(struct sockaddr_in *be)
+{
+    int     i, n;
+    GROUP   *g;
+
+    if(alive_to <= 0)
+        return;
+    for(n = 0; (g = groups[n]) != NULL; n++) {
+        pthread_mutex_lock(&g->mut);
+        for(i = 0; i < g->tot_pri; i++)
+            if(memcmp(&(g->backend_addr[i].addr), be, sizeof(*be)) == 0) {
+                if (g->backend_addr[i].timeout != 0) {
+                    /* killtimer already ticking */ 
+                    if ((time(NULL) - g->backend_addr[i].timeout) > con_timeout_before_kill) {
+                        pthread_mutex_unlock(&g->mut);
+			logmsg(LOG_ERR,"Calling kill for %s from timeout_be()", inet_ntoa(be->sin_addr));
+                        return kill_be(&g->backend_addr[i].addr);
+                    } else {
+                        logmsg(LOG_ERR,"Killtimer ticking for %s left: %d seconds",
+				inet_ntoa(be->sin_addr), con_timeout_before_kill - (time(NULL) - g->backend_addr[i].timeout));
+                    }
+                } else {
+                    g->backend_addr[i].timeout = time(NULL);
+		    g->backend_addr[i].degraded = 1;
+		    logmsg(LOG_ERR,"Killtimer started for %s", inet_ntoa(be->sin_addr));
+                }
+            }
+        pthread_mutex_unlock(&g->mut);
+    }
+    return;
+}
+
+
+/*
+ * degrade backend, no new sessions will be put there
+ * old ones are not killed though
+ */
+void degrade_be(struct sockaddr_in *be) {
+    int i, n;
+    GROUP *g;
+
+    for(n = 0; (g = groups[n]) != NULL; n++) {
+        pthread_mutex_lock(&g->mut);
+        for(i = 0; i < g->tot_pri; i++) {
+            if(memcmp(&(g->backend_addr[i].addr), be, sizeof(*be)) == 0) {
+                g->backend_addr[i].failed_alive_checks++;
+                if (g->backend_addr[i].failed_alive_checks > alive_checks_before_kill) {
+                    pthread_mutex_unlock(&g->mut);
+                    return kill_be(&g->backend_addr[i].addr);
+                } else {
+                    logmsg(LOG_ERR,"Host %s degraded with %d alive checks left.",
+			inet_ntoa(be->sin_addr), alive_checks_before_kill - g->backend_addr[i].failed_alive_checks);
+                    g->backend_addr[i].degraded = 1;
+                }
+            }
+        }
+	pthread_mutex_unlock(&g->mut);
+    }
     return;
 }
 
@@ -844,8 +913,8 @@
         memset(&z_addr, 0, sizeof(z_addr));
         for(n = 0; (g = groups[n]) != NULL; n++) {
             for(i = 0; i < g->tot_pri; i++) {
-                if(!g->backend_addr[i].alive)
-                    /* already dead */
+                if(!g->backend_addr[i].alive || g->backend_addr[i].degraded)
+                    /* already dead or degraded */
                     continue;
                 if(memcmp(&(g->backend_addr[i].alive_addr), &z_addr, sizeof(z_addr)) == 0)
                     /* no HA port */
@@ -855,8 +924,12 @@
                     continue;
                 addr = g->backend_addr[i].alive_addr;
                 if(connect_nb(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) {
-                    kill_be(&g->backend_addr[i].addr);
-                    logmsg(LOG_ERR,"BackEnd %s is dead", inet_ntoa(g->backend_addr[i].addr.sin_addr));
+                    degrade_be(&g->backend_addr[i].addr);
+		    /*
+                    logmsg(LOG_ERR,"BackEnd %s is degraded - check %d of %d failed", 
+			inet_ntoa(g->backend_addr[i].addr.sin_addr), g->backend_addr[i].failed_alive_checks,
+			alive_checks_before_kill);
+                    */
                 }
                 shutdown(sock, 2);
                 close(sock);
@@ -865,7 +938,7 @@
         /* check hosts alive again */
         for(n = 0; (g = groups[n]) != NULL; n++) {
             for(i = 0; i < g->tot_pri; i++) {
-                if(g->backend_addr[i].alive)
+                if(g->backend_addr[i].alive && !g->backend_addr[i].degraded) 
                     continue;
                 if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
                     continue;
@@ -878,10 +951,22 @@
                     addr = g->backend_addr[i].addr;
                     for(j = i; j < g->tot_pri; j++)
                         if(memcmp(&(g->backend_addr[j].addr), &addr, sizeof(addr)) == 0) {
-                            g->backend_addr[j].alive = 1;
-                            logmsg(LOG_ERR,"BackEnd %s resurrect", inet_ntoa(g->backend_addr[i].addr.sin_addr));
+                            if (g->backend_addr[j].degraded) {
+                                g->backend_addr[j].degraded = 0;
+				g->backend_addr[j].timeout = 0;
+                                g->backend_addr[j].failed_alive_checks = 0;
+                                logmsg(LOG_ERR,"BackEnd %s degraded -> functional", inet_ntoa(g->backend_addr[i].addr.sin_addr));
+                            } else {
+                                g->backend_addr[j].alive = 1;
+				g->backend_addr[j].failed_alive_checks = 0;
+				g->backend_addr[j].timeout = 0;
+                                logmsg(LOG_ERR,"BackEnd %s resurrect", inet_ntoa(g->backend_addr[i].addr.sin_addr));
+                            }
                         }
                     pthread_mutex_unlock(&g->mut);
+                } else if (g->backend_addr[i].alive) {
+	            /* con failed again, and it's still alive, lets see if it has any retries left */
+                    degrade_be(&g->backend_addr[i].addr);
                 }
                 shutdown(sock, 2);
                 close(sock);
