[PATCH 2/2] Fix memory leak in gets command.

Tomash Brechko tomash.brechko at gmail.com
Sun Nov 11 17:39:52 UTC 2007


The problem was in (redundant) item_get() without matching item_remove().

WARNING: while it fixes the leak, it also reveals the fact that CAS
never worked.  Included test fails, though it should succeed.  Instead
of committing this patch CAS should be fixed to use proper
generation counter.
---
 trunk/server/memcached.c  |    2 +-
 trunk/server/t/cas_race.t |   40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletions(-)
 create mode 100644 trunk/server/t/cas_race.t

diff --git a/trunk/server/memcached.c b/trunk/server/memcached.c
index e432cd6..3ac9503 100644
--- a/trunk/server/memcached.c
+++ b/trunk/server/memcached.c
@@ -1158,7 +1158,7 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
 
                 if(return_key_ptr == true)
                 {
-                  in_memory_ptr = (uint32_t)item_get(key, nkey);
+                  in_memory_ptr = (uint32_t)it;
                   sprintf(suffix," %d %d %lu\r\n", atoi(ITEM_suffix(it) + 1), it->nbytes - 2, in_memory_ptr);
                   if (add_iov(c, "VALUE ", 6) != 0 ||
                       add_iov(c, ITEM_key(it), it->nkey) != 0 ||
diff --git a/trunk/server/t/cas_race.t b/trunk/server/t/cas_race.t
new file mode 100644
index 0000000..656c4d6
--- /dev/null
+++ b/trunk/server/t/cas_race.t
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use strict;
+use Test::More tests => 5;
+use FindBin qw($Bin);
+use lib "$Bin/lib";
+use MemcachedTest;
+
+
+my $server = new_memcached();
+my $sock = $server->sock;
+
+
+my (@res1, @res2);
+
+# THREAD 1: store foo value
+print $sock "set foo 0 0 6\r\nbarval\r\n";
+is(scalar <$sock>, "STORED\r\n", "stored barval");
+
+# THREAD 1: find out foo CAS
+ at res1 = mem_gets($sock, "foo");
+
+# THREAD 2: find out foo CAS
+ at res2 = mem_gets($sock, "foo");
+
+# CAS values are the same in both threads.
+is($res1[0], $res2[0]);
+
+# THREAD 1: CAS update: here we get the new address/CAS.
+print $sock "cas foo 0 0 6 $res1[0]\r\nbarva2\r\n";
+is(scalar <$sock>, "STORED\r\n", "cas success, set foo");
+
+# THREAD 1: CAS update: here we get back the _old_ address/CAS.
+ at res1 = mem_gets($sock, "foo");
+print $sock "cas foo 0 0 6 $res1[0]\r\nbarva3\r\n";
+is(scalar <$sock>, "STORED\r\n", "cas success, set foo");
+
+# THREAD 2: CAS update: success because the address was reused.
+print $sock "cas foo 0 0 6 $res2[0]\r\nBUGBUG\r\n";
+is(scalar <$sock>, "EXISTS\r\n", "cas failure (should be)");
-- 
1.5.3.5.529.ge3d6d


More information about the memcached mailing list