]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: servers: Use atomic operations when handling curr_idle_conns.
authorOlivier Houchard <ohouchard@haproxy.com>
Fri, 15 Feb 2019 17:49:15 +0000 (18:49 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 21 Feb 2019 18:07:19 +0000 (19:07 +0100)
Use atomic operations when dealing with srv->curr_idle_conns, as it's shared
between threads, otherwise we could get inconsistencies.

This should be backported to 1.9.

include/proto/connection.h
include/proto/server.h
src/backend.c

index 335757ed82e3026c8d88d15083a9417d1b814343..1dc0512f417cecc72d52a8887e4ddd09279faef9 100644 (file)
@@ -693,7 +693,7 @@ static inline void conn_free(struct connection *conn)
         */
        if (conn->idle_time > 0) {
                struct server *srv = __objt_server(conn->target);
-               srv->curr_idle_conns--;
+               HA_ATOMIC_SUB(&srv->curr_idle_conns, 1);
        }
 
        conn_force_unsubscribe(conn);
index fa36e8deb9cb58a5f7ccfaa9515e2c194225c532..51d1015e98f8312e4dd019e5e30707b893dbacea 100644 (file)
@@ -244,9 +244,15 @@ static inline int srv_add_to_idle_list(struct server *srv, struct connection *co
            !(conn->flags & CO_FL_PRIVATE) &&
            ((srv->proxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) &&
            !conn->mux->used_streams(conn) && conn->mux->avail_streams(conn)) {
+               int retadd;
+
+               retadd = HA_ATOMIC_ADD(&srv->curr_idle_conns, 1);
+               if (retadd >= srv->max_idle_conns) {
+                       HA_ATOMIC_SUB(&srv->curr_idle_conns, 1);
+                       return 0;
+               }
                LIST_DEL(&conn->list);
                LIST_ADDQ(&srv->idle_orphan_conns[tid], &conn->list);
-               srv->curr_idle_conns++;
 
                conn->idle_time = now_ms;
                if (!(task_in_wq(srv->idle_task[tid])) &&
index 1fd66f932a3393051cd29f2c60abefcf06d2a705..3c752a273b999492a5f4f732937c737d7d6bf26b 100644 (file)
@@ -1343,7 +1343,7 @@ int connect_server(struct stream *s)
        if (reuse && reuse_orphan) {
                LIST_DEL(&srv_conn->list);
                srv_conn->idle_time = 0;
-               srv->curr_idle_conns--;
+               HA_ATOMIC_SUB(&srv->curr_idle_conns, 1);
                LIST_ADDQ(&srv->idle_conns[tid], &srv_conn->list);
                if (LIST_ISEMPTY(&srv->idle_orphan_conns[tid]))
                        task_unlink_wq(srv->idle_task[tid]);