Cache::Memcached - pos() weirdness

Dave Evans memcached-list-20040309@djce.org.uk
Thu, 20 May 2004 12:15:13 +0100


This is a multi-part message in MIME format.
--------------040507020400070700040305
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

A few times I've come across some rather odd behaviour in the Perl binding,
Cache::Memcached.  Typically the following warning is emitted:

  Use of uninitialized value in subtraction (-) at Cache/Memcached.pm line 494.

which is this line:

  my $copy = $len-$p > $state{$sock} ? $state{$sock} : $len-$p;

The cause seems to be that pos() has returned "undef" - this in spite of the
fact that the last m//g match was successful (just a few lines further up).
"perldoc -f pos" tells us that undef() is returned if and only if the match
failed.  So, I'm at a loss to explain what's going on.  I'd love to hear an
explanation, if anyone has one.

What I /can/ be sure about is that when it does happen, it causes problems,
because effectively the whole response "VALUE key n n ..." is interpreted as the
value from the cache.  Ooops.

Because I have no idea why pos() is playing up, I modifed the code not to rely
on pos() any more, which makes this problem go away (for me).  Patch attached.

Thanks,

-- 
Dave Evans

PGP key: http://rudolf.org.uk/pgpkey


--------------040507020400070700040305
Content-Type: text/plain;
 name="memcached-pos-weirdness.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="memcached-pos-weirdness.patch"

--- Cache-Memcached-1.0.12/Memcached.pm	Thu May 20 08:32:02 2004
+++ Cache-Memcached-1.0.12/Memcached.pm	Thu May 20 10:58:18 2004
@@ -486,10 +486,9 @@
             }
 
             # do we have a complete VALUE line?
-            if ($buf{$sock} =~ /^VALUE (\S+) (\d+) (\d+)\r\n/g) {
-                ($key{$sock}, $flags{$sock}, $state{$sock}) = ($1, int($2), $3+2);
-                my $p = pos($buf{$sock});
-                pos($buf{$sock}) = 0;
+            if ($buf{$sock} =~ /^(VALUE (\S+) (\d+) (\d+)\r\n)/) {
+                ($key{$sock}, $flags{$sock}, $state{$sock}) = ($2, int($3), $4+2);
+                my $p = length($1);
                 my $len = length($buf{$sock});
                 my $copy = $len-$p > $state{$sock} ? $state{$sock} : $len-$p;
                 $ret->{$key{$sock}} = substr($buf{$sock}, $p, $copy)

--------------040507020400070700040305--