]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: cli: show sess <id> may randomly corrupt the back-ref list
authorWilly Tarreau <w@1wt.eu>
Mon, 26 Nov 2012 01:22:40 +0000 (02:22 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 26 Nov 2012 01:22:40 +0000 (02:22 +0100)
show sess <id> puts a backref into the session it's dumping. If the output
is interrupted, the backref cannot always be removed because it's only done
in the I/O handler. This can randomly corrupt the backref list when the
session closes, because it passes the pointer to the next session which
itself might be watched.

The case is hard to reproduce (hundreds of attempts) but monitoring systems
might encounter it frequently.

Thus we have to add a release handler which does the cleanup even when the
I/O handler is not called.

This issue should also be present in 1.4 so the patch should be backported.

src/dumpstats.c

index 0b1c64ce79c4789168028438d3b5e63d8cb26f4f..ad54725fb36203f4ca170357fd76cedb2b3ed07f 100644 (file)
@@ -3911,6 +3911,18 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
        }
 }
 
+/* This is called when the stream interface is closed. For instance, upon an
+ * external abort, we won't call the i/o handler anymore so we may need to
+ * remove back references to the session currently being dumped.
+ */
+void cli_release_handler(struct stream_interface *si)
+{
+       if (si->applet.st0 == STAT_CLI_O_SESS && si->conn->xprt_st == STAT_ST_LIST) {
+               if (!LIST_ISEMPTY(&si->applet.ctx.sess.bref.users))
+                       LIST_DEL(&si->applet.ctx.sess.bref.users);
+       }
+}
+
 /* This function dumps all tables' states onto the stream interface's
  * read buffer. The xprt_ctx must have been zeroed first, and the flags
  * properly set. It returns 0 if the output buffer is full and it needs
@@ -4318,7 +4330,7 @@ static struct si_applet cli_applet = {
        .obj_type = OBJ_TYPE_APPLET,
        .name = "<CLI>", /* used for logging */
        .fct = cli_io_handler,
-       .release = NULL,
+       .release = cli_release_handler,
 };
 
 static struct cfg_kw_list cfg_kws = {{ },{