From 92b10c954defc82ceabdc9bba923320a157c664d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 4 Dec 2016 20:05:16 +0100 Subject: [PATCH] BUG/MAJOR: stream: fix session abort on resource shortage In 1.6-dev2, commit 32990b5 ("MEDIUM: session: remove the task pointer from the session") introduced a bug which can sometimes crash the process on resource shortage. When stream_complete() returns -1, it has already reattached the connection to the stream, then kill_mini_session() is called and still expects to find the task in conn->owner. Note that since this commit, the code has moved a bit and is now in stream_new() but the problem remains the same. Given that we already know the task around these places, let's simply pass the task to kill_mini_session(). The conditions currently at risk are : - failure to initialize filters for the new stream (lack of memory or any filter returning < 0 on attach()) - failure to attach filters (any filter returning < 0 on stream_start()) - frontend's accept() returning < 0 (allocation failure) This fix is needed in 1.7 and 1.6. --- src/session.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/session.c b/src/session.c index 8c8508347..35177cf20 100644 --- a/src/session.c +++ b/src/session.c @@ -342,11 +342,10 @@ static void session_prepare_log_prefix(struct session *sess) * disabled and finally kills the file descriptor. This function requires that * sess->origin points to the incoming connection. */ -static void session_kill_embryonic(struct session *sess) +static void session_kill_embryonic(struct session *sess, struct task *task) { int level = LOG_INFO; struct connection *conn = __objt_conn(sess->origin); - struct task *task = conn->owner; unsigned int log = sess->fe->to_log; const char *err_msg; @@ -417,7 +416,7 @@ static struct task *session_expire_embryonic(struct task *t) if (!(t->state & TASK_WOKEN_TIMER)) return t; - session_kill_embryonic(sess); + session_kill_embryonic(sess, t); return NULL; } @@ -457,7 +456,7 @@ static int conn_complete_session(struct connection *conn) return 0; fail: - session_kill_embryonic(sess); + session_kill_embryonic(sess, task); return -1; } @@ -470,7 +469,7 @@ static int conn_update_session(struct connection *conn) struct session *sess = task->context; if (conn->flags & CO_FL_ERROR) { - session_kill_embryonic(sess); + session_kill_embryonic(sess, task); return -1; } return 0;