On Tue, Dec 08, 2015 at 07:44:45AM +0530, Krishna Kumar (Engineering) wrote:
> Great, will be glad to test and report on the finding. Thanks!

Sorry I forgot to post the patch after committing it. Here it comes.
Regarding the second point, in the end it's not a bug, it's simply
because we don't have connection pools yet, and I forgot that keeping
an orphan backend connection was only possible with connection pools :-)

Willy

commit 58b318c613b6209d6fe3c9ad38cd11f6814bf7ab
Author: Willy Tarreau <[email protected]>
Date:   Mon Dec 7 17:04:59 2015 +0100

    BUG/MEDIUM: http: fix http-reuse when frontend and backend differ
    
    Krishna Kumar reported that the following configuration doesn't permit
    HTTP reuse between two clients :
    
        frontend private-frontend
            mode http
            bind :8001
            default_backend private-backend
    
        backend private-backend
            mode http
            http-reuse always
            server bck 127.0.0.1:8888
    
    The reason for this is that in http_end_txn_clean_session() we check the
    stream's backend backend's http-reuse option before deciding whether the
    backend connection should be moved back to the server's pool or not. But
    since we're doing this after the call to http_reset_txn(), the backend is
    reset to match the frontend, which doesn't have the option. However it
    will work fine in a setup involving a "listen" section.
    
    We just need to keep a pointer to the current backend before calling
    http_reset_txn(). The code does that and replaces the few remaining
    references to s->be inside the same function so that if any part of
    code were to be moved later, this trap doesn't happen again.
    
    This fix must be backported to 1.6.
    (cherry picked from commit 858b103631db41c608660210eb37a9e09ee9f086)

diff --git a/src/proto_http.c b/src/proto_http.c
index 1d00071..5fea6c4 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5120,6 +5120,7 @@ void http_end_txn_clean_session(struct stream *s)
 {
        int prev_status = s->txn->status;
        struct proxy *fe = strm_fe(s);
+       struct proxy *be = s->be;
        struct connection *srv_conn;
        struct server *srv;
        unsigned int prev_flags = s->txn->flags;
@@ -5142,7 +5143,7 @@ void http_end_txn_clean_session(struct stream *s)
        }
 
        if (s->flags & SF_BE_ASSIGNED) {
-               s->be->beconn--;
+               be->beconn--;
                if (unlikely(s->srv_conn))
                        sess_change_server(s, NULL);
        }
@@ -5163,11 +5164,11 @@ void http_end_txn_clean_session(struct stream *s)
                                fe->fe_counters.p.http.comp_rsp++;
                }
                if ((s->flags & SF_BE_ASSIGNED) &&
-                   (s->be->mode == PR_MODE_HTTP)) {
-                       s->be->be_counters.p.http.rsp[n]++;
-                       s->be->be_counters.p.http.cum_req++;
+                   (be->mode == PR_MODE_HTTP)) {
+                       be->be_counters.p.http.rsp[n]++;
+                       be->be_counters.p.http.cum_req++;
                        if (s->comp_algo && (s->flags & SF_COMP_READY))
-                               s->be->be_counters.p.http.comp_rsp++;
+                               be->be_counters.p.http.comp_rsp++;
                }
        }
 
@@ -5207,7 +5208,7 @@ void http_end_txn_clean_session(struct stream *s)
                        s->flags &= ~SF_CURR_SESS;
                        objt_server(s->target)->cur_sess--;
                }
-               if (may_dequeue_tasks(objt_server(s->target), s->be))
+               if (may_dequeue_tasks(objt_server(s->target), be))
                        process_srv_queue(objt_server(s->target));
        }
 
@@ -5286,7 +5287,7 @@ void http_end_txn_clean_session(struct stream *s)
                if (!srv)
                        si_idle_conn(&s->si[1], NULL);
                else if ((srv_conn->flags & CO_FL_PRIVATE) ||
-                        ((s->be->options & PR_O_REUSE_MASK) == 
PR_O_REUSE_NEVR))
+                        ((be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR))
                        si_idle_conn(&s->si[1], &srv->priv_conns);
                else if (prev_flags & TX_NOT_FIRST)
                        /* note: we check the request, not the connection, but

Reply via email to