]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG: queue: fix dequeueing sequence on HTTP keep-alive sessions
authorWilly Tarreau <w@1wt.eu>
Thu, 1 Mar 2012 22:34:37 +0000 (23:34 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 1 Mar 2012 22:49:20 +0000 (23:49 +0100)
When a request completes on a server and the server connection is closed
while the client connection stays open, the HTTP engine releases all server
connection slots and scans the queues to offer the connection slot to
another pending request.

An issue happens when the released connection allows other requests to be
dequeued : may_dequeue_tasks() relies on srv->served which is only decremented
by sess_change_server() which itself is only called after may_dequeue_tasks().
This results in no connection being woken up until another connection terminates
so that may_dequeue_tasks() is called again.

This fix is minimalist and only moves sess_change_server() earlier (which is
safe). It should be reworked and the code factored out so that the same occurrence
in session.c shares the same code.

This bug has been there since the introduction of option-http-server-close and
the fix must be backported to 1.4.

src/proto_http.c

index 5efc7ec7518d9319df2608e8f40d3dde716ed6c8..f36dc3c73c01e2023673a3f7578b003f6a71517d 100644 (file)
@@ -4035,8 +4035,11 @@ void http_end_txn_clean_session(struct session *s)
 
        http_silent_debug(__LINE__, s);
 
-       if (s->flags & SN_BE_ASSIGNED)
+       if (s->flags & SN_BE_ASSIGNED) {
                s->be->beconn--;
+               if (unlikely(s->srv_conn))
+                       sess_change_server(s, NULL);
+       }
 
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
        session_process_counters(s);
@@ -4093,8 +4096,6 @@ void http_end_txn_clean_session(struct session *s)
                        process_srv_queue(target_srv(&s->target));
        }
 
-       if (unlikely(s->srv_conn))
-               sess_change_server(s, NULL);
        clear_target(&s->target);
 
        s->req->cons->state     = s->req->cons->prev_state = SI_ST_INI;