From: Willy Tarreau Date: Wed, 29 Nov 2017 13:05:38 +0000 (+0100) Subject: BUG/MEDIUM: stream: fix session leak on applet-initiated connections X-Git-Tag: v1.9-dev1~644 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5bcfd56519b683386643c800558714893fd33910;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stream: fix session leak on applet-initiated connections Commit 3e13cba ("MEDIUM: session: make use of the connection's destroy callback") ensured that connections could be autonomous to destroy the session they initiated, but it didn't take care of doing the same for applets. Such applets are used for peers, Lua and SPOE outgoing connections. In this case, once the stream ends, it closes everything and nothing takes care of releasing the session. The problem is not immediately obvious since the only visible effect is that older processes will not quit on reload after having leaked one such session. For now we check in stream_free() if the session's origin is the applet we're releasing, and then free the session as well. Something more uniform should probably be done once we manage to unify applets and connections a bit more. This fix needs to be backported to 1.8. Thanks to Emmanuel Hocdet for reporting the problem. --- diff --git a/src/stream.c b/src/stream.c index 7d7910d945..32da7c2e35 100644 --- a/src/stream.c +++ b/src/stream.c @@ -297,6 +297,7 @@ static void stream_free(struct stream *s) struct proxy *fe = sess->fe; struct bref *bref, *back; struct conn_stream *cli_cs = objt_cs(s->si[0].end); + int must_free_sess; int i; if (s->pend_pos) @@ -388,12 +389,15 @@ static void stream_free(struct stream *s) LIST_DEL(&s->list); HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock); + /* applets do not release session yet */ + must_free_sess = objt_appctx(sess->origin) && sess->origin == s->si[0].end; + si_release_endpoint(&s->si[1]); si_release_endpoint(&s->si[0]); - /* FIXME: for now we have a 1:1 relation between stream and session so - * the stream must free the session. - */ + if (must_free_sess) + session_free(sess); + pool_free(pool_head_stream, s); /* We may want to free the maximum amount of pools if the proxy is stopping */