]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: threads/server: Make connection list (priv/idle/safe) thread-safe
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 3 Jul 2017 13:41:01 +0000 (15:41 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 12:58:30 +0000 (13:58 +0100)
For now, we have a list of each type per thread. So there is no need to lock
them. This is the easiest solution for now, but not the best one because there
is no sharing between threads. An idle connection on a thread will not be able
be used by a stream on another thread. So it could be a good idea to rework this
patch later.

include/types/server.h
src/backend.c
src/hlua.c
src/proto_http.c
src/server.c

index 69397c1ca27459ecb52737ecdee26b54fa71c02f..ecf04d7c9efe13d170078cb779053b37be1b8236 100644 (file)
@@ -207,9 +207,9 @@ struct server {
 
        struct list pendconns;                  /* pending connections */
        struct list actconns;                   /* active connections */
-       struct list priv_conns;                 /* private idle connections attached to stream interfaces */
-       struct list idle_conns;                 /* sharable idle connections attached or not to a stream interface */
-       struct list safe_conns;                 /* safe idle connections attached to stream interfaces, shared */
+       struct list *priv_conns;                /* private idle connections attached to stream interfaces */
+       struct list *idle_conns;                /* sharable idle connections attached or not to a stream interface */
+       struct list *safe_conns;                /* safe idle connections attached to stream interfaces, shared */
        struct task *warmup;                    /* the task dedicated to the warmup when slowstart is set */
 
        struct conn_src conn_src;               /* connection source settings */
index 475efa36d8a6638fc3ff7d7c42c4fcb498dec252..5e51f39eafc85edc23db2c0eec4efb70558d21d9 100644 (file)
@@ -1066,20 +1066,19 @@ int connect_server(struct stream *s)
                 *  idle|  -  |  1  |    idle|  -  |  1  |   idle|  2  |  1  |
                 *  ----+-----+-----+    ----+-----+-----+   ----+-----+-----+
                 */
-
-               if (!LIST_ISEMPTY(&srv->idle_conns) &&
+               if (srv->idle_conns && !LIST_ISEMPTY(&srv->idle_conns[tid]) &&
                    ((s->be->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR &&
                     s->txn && (s->txn->flags & TX_NOT_FIRST))) {
-                       srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+                       srv_conn = LIST_ELEM(srv->idle_conns[tid].n, struct connection *, list);
                }
-               else if (!LIST_ISEMPTY(&srv->safe_conns) &&
+               else if (srv->safe_conns && !LIST_ISEMPTY(&srv->safe_conns[tid]) &&
                         ((s->txn && (s->txn->flags & TX_NOT_FIRST)) ||
                          (s->be->options & PR_O_REUSE_MASK) >= PR_O_REUSE_AGGR)) {
-                       srv_conn = LIST_ELEM(srv->safe_conns.n, struct connection *, list);
+                       srv_conn = LIST_ELEM(srv->safe_conns[tid].n, struct connection *, list);
                }
-               else if (!LIST_ISEMPTY(&srv->idle_conns) &&
+               else if (srv->idle_conns && !LIST_ISEMPTY(&srv->idle_conns[tid]) &&
                         (s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) {
-                       srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+                       srv_conn = LIST_ELEM(srv->idle_conns[tid].n, struct connection *, list);
                }
 
                /* If we've picked a connection from the pool, we now have to
index 137117c586532de654bd16e93c111a139da0b473..36b1b3ff4df4044b0473186d212b3f0c3d8f5899 100644 (file)
@@ -7666,9 +7666,9 @@ void hlua_init(void)
        socket_tcp.obj_type = OBJ_TYPE_SERVER;
        LIST_INIT(&socket_tcp.actconns);
        LIST_INIT(&socket_tcp.pendconns);
-       LIST_INIT(&socket_tcp.priv_conns);
-       LIST_INIT(&socket_tcp.idle_conns);
-       LIST_INIT(&socket_tcp.safe_conns);
+       socket_tcp.priv_conns = NULL;
+       socket_tcp.idle_conns = NULL;
+       socket_tcp.safe_conns = NULL;
        socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
        socket_tcp.last_change = 0;
        socket_tcp.id = "LUA-TCP-CONN";
@@ -7712,9 +7712,9 @@ void hlua_init(void)
        socket_ssl.obj_type = OBJ_TYPE_SERVER;
        LIST_INIT(&socket_ssl.actconns);
        LIST_INIT(&socket_ssl.pendconns);
-       LIST_INIT(&socket_ssl.priv_conns);
-       LIST_INIT(&socket_ssl.idle_conns);
-       LIST_INIT(&socket_ssl.safe_conns);
+       socket_tcp.priv_conns = NULL;
+       socket_tcp.idle_conns = NULL;
+       socket_tcp.safe_conns = NULL;
        socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
        socket_ssl.last_change = 0;
        socket_ssl.id = "LUA-SSL-CONN";
index cfc0e728569ddce07cd04eb950311fbc1473360b..cf1cc7af2bd51b8cd465a79985aef3adad1c429f 100644 (file)
@@ -4348,15 +4348,15 @@ 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)
-                       si_idle_conn(&s->si[1], &srv->priv_conns);
+                       si_idle_conn(&s->si[1], (srv->priv_conns ? &srv->priv_conns[tid] : NULL));
                else if (prev_flags & TX_NOT_FIRST)
                        /* note: we check the request, not the connection, but
                         * this is valid for strategies SAFE and AGGR, and in
                         * case of ALWS, we don't care anyway.
                         */
-                       si_idle_conn(&s->si[1], &srv->safe_conns);
+                       si_idle_conn(&s->si[1], (srv->safe_conns ? &srv->safe_conns[tid] : NULL));
                else
-                       si_idle_conn(&s->si[1], &srv->idle_conns);
+                       si_idle_conn(&s->si[1], (srv->idle_conns ? &srv->idle_conns[tid] : NULL));
        }
        s->req.analysers = strm_li(s) ? strm_li(s)->analysers : 0;
        s->res.analysers = 0;
index 01a7d9b670d4702706a92d7023d6729d9389511e..4c70ac4ad46d84c944da610c3e6382791cf8b544 100644 (file)
@@ -1511,6 +1511,7 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp
 static struct server *new_server(struct proxy *proxy)
 {
        struct server *srv;
+       int i;
 
        srv = calloc(1, sizeof *srv);
        if (!srv)
@@ -1520,9 +1521,20 @@ static struct server *new_server(struct proxy *proxy)
        srv->proxy = proxy;
        LIST_INIT(&srv->actconns);
        LIST_INIT(&srv->pendconns);
-       LIST_INIT(&srv->priv_conns);
-       LIST_INIT(&srv->idle_conns);
-       LIST_INIT(&srv->safe_conns);
+
+       if ((srv->priv_conns = calloc(global.nbthread, sizeof(*srv->priv_conns))) == NULL)
+               goto free_srv;
+       if ((srv->idle_conns = calloc(global.nbthread, sizeof(*srv->idle_conns))) == NULL)
+               goto free_priv_conns;
+       if ((srv->safe_conns = calloc(global.nbthread, sizeof(*srv->safe_conns))) == NULL)
+               goto free_idle_conns;
+
+       for (i = 0; i < global.nbthread; i++) {
+               LIST_INIT(&srv->priv_conns[i]);
+               LIST_INIT(&srv->idle_conns[i]);
+               LIST_INIT(&srv->safe_conns[i]);
+       }
+
        LIST_INIT(&srv->update_status);
 
        srv->next_state = SRV_ST_RUNNING; /* early server setup */
@@ -1537,6 +1549,14 @@ static struct server *new_server(struct proxy *proxy)
        srv->xprt  = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW);
 
        return srv;
+
+  free_idle_conns:
+       free(srv->idle_conns);
+  free_priv_conns:
+       free(srv->priv_conns);
+  free_srv:
+       free(srv);
+       return NULL;
 }
 
 /*