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.
This commit is contained in:
Willy Tarreau 2017-11-29 14:05:38 +01:00
parent ec7464726f
commit 5bcfd56519

View File

@ -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 */