Skip to content

Commit 67df657

Browse files
committed
MEDIUM: server: close new idle conns if server in maintenance
Currently, when a server is set on maintenance mode, its idle connection are scheduled for purge. However, this does not prevent currently used connection to become idle later on, even if the server is still off. Change this behavior : an idle connection is now rejected by the server if it is in maintenance. This is implemented with a new condition in srv_add_to_idle_list() which returns an error value. In this case, muxes stream detach callback will immediately free the connection. A similar change is also performed in each MUX and SSL I/O handlers and in conn_notify_mux(). An idle connection is not reinserted in its idle list if server is in maintenance, but instead it is immediately freed.
1 parent f234b40 commit 67df657

File tree

7 files changed

+77
-18
lines changed

7 files changed

+77
-18
lines changed

src/connection.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ int conn_notify_mux(struct connection *conn, int old_flags, int forced_wake)
213213
goto done;
214214

215215
if (conn_in_list) {
216+
if (srv->cur_admin & SRV_ADMF_MAINT) {
217+
/* Do not store an idle conn if server in maintenance. */
218+
conn->mux->destroy(conn->ctx);
219+
ret = -1;
220+
goto done;
221+
}
222+
216223
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
217224
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
218225
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);

src/mux_fcgi.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,11 +3091,21 @@ struct task *fcgi_io_cb(struct task *t, void *ctx, unsigned int state)
30913091
if (!ret && conn_in_list) {
30923092
struct server *srv = __objt_server(conn->target);
30933093

3094-
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
3095-
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
3096-
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
3094+
if (!(srv->cur_admin & SRV_ADMF_MAINT)) {
3095+
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
3096+
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
3097+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
3098+
}
3099+
else {
3100+
/* Do not store an idle conn if server in maintenance. */
3101+
goto release;
3102+
}
30973103
}
30983104
return t;
3105+
3106+
release:
3107+
fcgi_release(fconn);
3108+
return NULL;
30993109
}
31003110

31013111
/* callback called on any event by the connection handler.

src/mux_h1.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4328,11 +4328,21 @@ struct task *h1_io_cb(struct task *t, void *ctx, unsigned int state)
43284328
if (!ret && conn_in_list) {
43294329
struct server *srv = __objt_server(conn->target);
43304330

4331-
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4332-
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
4333-
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4331+
if (!(srv->cur_admin & SRV_ADMF_MAINT)) {
4332+
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4333+
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
4334+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4335+
}
4336+
else {
4337+
/* Do not store an idle conn if server in maintenance. */
4338+
goto release;
4339+
}
43344340
}
43354341
return t;
4342+
4343+
release:
4344+
h1_release(h1c);
4345+
return NULL;
43364346
}
43374347

43384348
static int h1_wake(struct connection *conn)

src/mux_h2.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4995,14 +4995,25 @@ struct task *h2_io_cb(struct task *t, void *ctx, unsigned int state)
49954995
if (!ret && conn_in_list) {
49964996
struct server *srv = __objt_server(conn->target);
49974997

4998-
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4999-
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
5000-
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
4998+
if (!(srv->cur_admin & SRV_ADMF_MAINT)) {
4999+
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
5000+
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
5001+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
5002+
}
5003+
else {
5004+
/* Do not store an idle conn if server in maintenance. */
5005+
goto release;
5006+
}
50015007
}
50025008

5003-
leave:
5009+
leave:
50045010
TRACE_LEAVE(H2_EV_H2C_WAKE);
50055011
return t;
5012+
5013+
release:
5014+
TRACE_LEAVE(H2_EV_H2C_WAKE);
5015+
h2_release(h2c);
5016+
return NULL;
50065017
}
50075018

50085019
/* callback called on any event by the connection handler.

src/mux_spop.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,11 +2587,21 @@ static struct task *spop_io_cb(struct task *t, void *ctx, unsigned int state)
25872587
if (!ret && conn_in_list) {
25882588
struct server *srv = __objt_server(conn->target);
25892589

2590-
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
2591-
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
2592-
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
2590+
if (!(srv->cur_admin & SRV_ADMF_MAINT)) {
2591+
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
2592+
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
2593+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
2594+
}
2595+
else {
2596+
/* Do not store an idle conn if server in maintenance. */
2597+
goto release;
2598+
}
25932599
}
25942600
return t;
2601+
2602+
release:
2603+
spop_release(spop_conn);
2604+
return NULL;
25952605
}
25962606

25972607
/* callback called on any event by the connection handler.

src/server.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7327,6 +7327,7 @@ int srv_add_to_idle_list(struct server *srv, struct connection *conn, int is_saf
73277327
*/
73287328
if (!(conn->flags & CO_FL_PRIVATE) &&
73297329
srv && srv->pool_purge_delay > 0 &&
7330+
!(srv->cur_admin & SRV_ADMF_MAINT) &&
73307331
((srv->proxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) &&
73317332
ha_used_fds < global.tune.pool_high_count &&
73327333
(srv->max_idle_conns == -1 || srv->max_idle_conns > srv->curr_idle_conns) &&

src/ssl_sock.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6478,12 +6478,22 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
64786478
#endif
64796479
leave:
64806480
if (!ret && conn_in_list) {
6481-
struct server *srv = objt_server(conn->target);
6481+
struct server *srv = __objt_server(conn->target);
64826482

6483-
TRACE_DEVEL("adding conn back to idle list", SSL_EV_CONN_IO_CB, conn);
6484-
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
6485-
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
6486-
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
6483+
if (!(srv->cur_admin & SRV_ADMF_MAINT)) {
6484+
TRACE_DEVEL("adding conn back to idle list", SSL_EV_CONN_IO_CB, conn);
6485+
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
6486+
_srv_add_idle(srv, conn, conn_in_list == CO_FL_SAFE_LIST);
6487+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
6488+
}
6489+
else {
6490+
/* Do not store an idle conn if server in maintenance. */
6491+
6492+
/* Connection is idle which means MUX layer is already initialized. */
6493+
BUG_ON(!conn->mux);
6494+
conn->mux->destroy(conn->ctx);
6495+
t = NULL;
6496+
}
64876497
}
64886498
TRACE_LEAVE(SSL_EV_CONN_IO_CB, conn);
64896499
return t;

0 commit comments

Comments
 (0)