]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: cli: "clear table" must not kill entries that don't match condition
authorWilly Tarreau <w@1wt.eu>
Tue, 13 Aug 2013 14:44:40 +0000 (16:44 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 13 Aug 2013 14:50:32 +0000 (16:50 +0200)
Mark Brooks reported the following issue :

"My table looks like this -

  0x24a8294: key=192.168.136.10 use=0 exp=1761492 server_id=3
  0x24a8344: key=192.168.136.11 use=0 exp=1761506 server_id=2
  0x24a83f4: key=192.168.136.12 use=0 exp=1761520 server_id=3
  0x24a84a4: key=192.168.136.13 use=0 exp=1761534 server_id=2
  0x24a8554: key=192.168.136.14 use=0 exp=1761548 server_id=3
  0x24a8604: key=192.168.136.15 use=0 exp=1761563 server_id=2
  0x24a86b4: key=192.168.136.16 use=0 exp=1761580 server_id=3
  0x24a8764: key=192.168.136.17 use=0 exp=1761592 server_id=2
  0x24a8814: key=192.168.136.18 use=0 exp=1761607 server_id=3
  0x24a88c4: key=192.168.136.19 use=0 exp=1761622 server_id=2
  0x24a8974: key=192.168.136.20 use=0 exp=1761636 server_id=3
  0x24a8a24: key=192.168.136.21 use=0 exp=1761649 server_id=2

im running the command -

  socat unix-connect:/var/run/haproxy.stat stdio <<< 'clear table VIP_Name-2 data.server_id eq 2'

Id assume that the entries with server_id = 2 would be removed but its
removing everything each time."

The cause of the issue is a missing test for skip_entry when deciding
whether to clear the key or not. The test was present when only the
last node is to be removed, so removing only the first node from a
list of two always did the right thing, explaining why it remained
unnoticed in basic unit tests.

The bug was introduced by commit 8fa52f4e which attempted to fix a
previous issue with this feature where only the last node was removed.

This bug is 1.5-specific and does not require any backport.

src/dumpstats.c

index 46066b5e2e635376e01f0bbabe3832a870cacf7f..8707e22ba9e9b37a0b3c67302065874271a55672 100644 (file)
@@ -4170,7 +4170,7 @@ static int stats_table_request(struct stream_interface *si, int action)
                                si->applet.ctx.table.entry = ebmb_entry(eb, struct stksess, key);
                                if (show)
                                        stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, old);
-                               else
+                               else if (!skip_entry && !si->applet.ctx.table.entry->ref_cnt)
                                        stksess_kill(&si->applet.ctx.table.proxy->table, old);
                                si->applet.ctx.table.entry->ref_cnt++;
                                break;