From a2a64e968993ecbb89903dd9b42ca2c7c792f194 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 7 Sep 2011 23:01:56 +0200 Subject: [PATCH] [MEDIUM] session: make session_shutdown() an independant function We already had the ability to kill a connection, but it was only for the checks. Now we can do this for any session, and for this we add a specific flag "K" to the logs. --- doc/configuration.txt | 2 ++ include/proto/session.h | 2 ++ include/types/session.h | 3 ++- src/checks.c | 15 +++------------ src/log.c | 2 +- src/session.c | 13 +++++++++++++ 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 2e2493e9f3..a8647467bb 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -8872,6 +8872,8 @@ each of which has a special meaning : D : the session was killed by haproxy because the server was detected as down and was configured to kill all connections when going down. + K : the session was actively killed by an admin operating on haproxy. + c : the client-side timeout expired while waiting for the client to send or receive data. diff --git a/include/proto/session.h b/include/proto/session.h index 78a22226b5..fb2b6a6605 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -36,6 +36,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr); /* perform minimal intializations, report 0 in case of error, 1 if OK. */ int init_session(); +/* kill a session and set the termination flags to (one of SN_ERR_*) */ +void session_shutdown(struct session *session, int why); void session_process_counters(struct session *s); void sess_change_server(struct session *sess, struct server *newsrv); diff --git a/include/types/session.h b/include/types/session.h index 605492489c..a707aa52e1 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -56,7 +56,7 @@ #define SN_REDIRECTABLE 0x00000400 /* set if this session is redirectable (GET or HEAD) */ #define SN_TUNNEL 0x00000800 /* tunnel-mode session, nothing to catch after data */ -/* session termination conditions, bits values 0x1000 to 0x7000 (0-7 shift 12) */ +/* session termination conditions, bits values 0x1000 to 0x7000 (0-9 shift 12) */ #define SN_ERR_NONE 0x00000000 #define SN_ERR_CLITO 0x00001000 /* client time-out */ #define SN_ERR_CLICL 0x00002000 /* client closed (read/write error) */ @@ -66,6 +66,7 @@ #define SN_ERR_RESOURCE 0x00006000 /* the proxy encountered a lack of a local resources (fd, mem, ...) */ #define SN_ERR_INTERNAL 0x00007000 /* the proxy encountered an internal error */ #define SN_ERR_DOWN 0x00008000 /* the proxy killed a session because the backend became unavailable */ +#define SN_ERR_KILLED 0x00009000 /* the proxy killed a session because it was asked to do so */ #define SN_ERR_MASK 0x0000f000 /* mask to get only session error flags */ #define SN_ERR_SHIFT 12 /* bit shift */ diff --git a/src/checks.c b/src/checks.c index 6a102dfd4c..f0338d7cfc 100644 --- a/src/checks.c +++ b/src/checks.c @@ -364,18 +364,9 @@ static void shutdown_sessions(struct server *srv) { struct session *session, *session_bck; - list_for_each_entry_safe(session, session_bck, - &srv->actconns, by_srv) { - if (session->srv_conn == srv && - !(session->req->flags & (BF_SHUTW|BF_SHUTW_NOW))) { - buffer_shutw_now(session->req); - buffer_shutr_now(session->rep); - session->task->nice = 1024; - if (!(session->flags & SN_ERR_MASK)) - session->flags |= SN_ERR_DOWN; - task_wakeup(session->task, TASK_WOKEN_OTHER); - } - } + list_for_each_entry_safe(session, session_bck, &srv->actconns, by_srv) + if (session->srv_conn == srv) + session_shutdown(session, SN_ERR_DOWN); } /* Sets server down, notifies by all available means, recounts the diff --git a/src/log.c b/src/log.c index d750349409..b62eedae77 100644 --- a/src/log.c +++ b/src/log.c @@ -52,7 +52,7 @@ const char *monthname[12] = { "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -const char sess_term_cond[9] = "-cCsSPRID"; /* normal, CliTo, CliErr, SrvTo, SrvErr, PxErr, Resource, Internal, Down */ +const char sess_term_cond[10] = "-cCsSPRIDK"; /* normal, CliTo, CliErr, SrvTo, SrvErr, PxErr, Resource, Internal, Down, Killed */ const char sess_fin_state[8] = "-RCHDLQT"; /* cliRequest, srvConnect, srvHeader, Data, Last, Queue, Tarpit */ /* diff --git a/src/session.c b/src/session.c index 5032d889bb..d39da99655 100644 --- a/src/session.c +++ b/src/session.c @@ -2214,6 +2214,19 @@ void default_srv_error(struct session *s, struct stream_interface *si) s->flags |= fin; } +/* kill a session and set the termination flags to (one of SN_ERR_*) */ +void session_shutdown(struct session *session, int why) +{ + if (session->req->flags & (BF_SHUTW|BF_SHUTW_NOW)) + return; + + buffer_shutw_now(session->req); + buffer_shutr_now(session->rep); + session->task->nice = 1024; + if (!(session->flags & SN_ERR_MASK)) + session->flags |= why; + task_wakeup(session->task, TASK_WOKEN_OTHER); +} /************************************************************************/ /* All supported ACL keywords must be declared here. */