From 40a007cf2a387bc2c4257840bafc54290297cbf9 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 3 Jul 2017 15:41:01 +0200 Subject: [PATCH] MEDIUM: threads/server: Make connection list (priv/idle/safe) thread-safe 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 | 6 +++--- src/backend.c | 13 ++++++------- src/hlua.c | 12 ++++++------ src/proto_http.c | 6 +++--- src/server.c | 26 +++++++++++++++++++++++--- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/include/types/server.h b/include/types/server.h index 69397c1ca2..ecf04d7c9e 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -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 */ diff --git a/src/backend.c b/src/backend.c index 475efa36d8..5e51f39eaf 100644 --- a/src/backend.c +++ b/src/backend.c @@ -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 diff --git a/src/hlua.c b/src/hlua.c index 137117c586..36b1b3ff4d 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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"; diff --git a/src/proto_http.c b/src/proto_http.c index cfc0e72856..cf1cc7af2b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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; diff --git a/src/server.c b/src/server.c index 01a7d9b670..4c70ac4ad4 100644 --- a/src/server.c +++ b/src/server.c @@ -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; } /* -- 2.39.5