possible bug in PHP API 1.0.8

Ryan Gilfether ryan@gilfether.com
Tue, 12 Aug 2003 19:25:17 -0400


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

Attached is a patch that fixes the problem found by Justin. His solution 
fixed the problem.

Thanks,
Ryan

Brad Fitzpatrick wrote:
> Justin,
> 
> Thanks!  The PHP client is known to be buggy (discovered last week), and
> Ryan said he's working on it.  Perhaps this is the only fix needed....
> 
> Ryan?
> 
> - Brad
> 
> 
> On Tue, 12 Aug 2003, Justin Matlock wrote:
> 
> 
>>Sorry for the extra-long email -- I just wanted to explain my thinking here,
>>and go into excessive detail so someone can prove me wrong. :)
>>
>>I'm using the latest CVS snapshot of memcached, and the 1.0.8 PHP API, and
>>the latest PHP 4.3.3 CVS tree, under Linux 2.4.21, Apache 2.0.47.  It was
>>all working great on my devel box, but when I moved it over to production, I
>>started getting a ton of "_load_items(): Bytes read is greater than
>>requested data size." errors.  But the thing is:  the development box and
>>production box are using the exact same memcached server.  They run the same
>>OS, the same PHP version, the same *everything*.  They're even the same
>>hardware (one serial number apart).  The *only* difference is the production
>>box is on the same subnet as the memcached server -- the development one is
>>on a different one.  Of course, I start doing a lot more testing on the
>>development box, and I notice I was getting them over there too, just not as
>>many.
>>
>>So I modified the script to give me more information (patch follows):
>>
>>=================
>>1063,1064c1063,1064
>><                                       $this->_debug("_load_items(): Bytes
>>read is greater than requested data size.");
>><
>>---
>>
>>>                                      $this->_debug("_load_items(): Bytes
>>
>>read ($bytes_read) is greater than requested data size ($len).");
>>
>>>                                      $this->_debug("_load_items(): I
>>
>>received \"".urlencode($buf)."\"");
>>=================
>>
>>Here's what I'm getting in my logs (I modified the debug handler to use my
>>custom logging routines) -- add 7 for the "\r\nEND\r\n".  So we're getting
>>back 2 characters instead of 1:
>>
>>(Data is "0")
>>[03Aug12 154857] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): Bytes
>>read (9) is greater than requested data size (1).
>>[03Aug12 154857] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): I
>>received "%0A2%0D%0AEND%0D%0A"
>>
>>(Data is "-1")
>>[03Aug12 154926] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): Bytes
>>read (10) is greater than requested data size (2).
>>[03Aug12 154926] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): I
>>received "%0A-1%0D%0AEND%0D%0A"
>>
>>(Data is a whole lot more than "0"  :) ):
>>[03Aug12 154926] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): Bytes
>>read (165) is greater than requested data size (157).
>>[03Aug12 154926] (INFO) #/profile/# <10.1.0.11> (u:1) _load_items(): I
>>received "%0Aa%3A1%3A%7Bi%3A0%3Ba%3A5%3A%7Bs%3A7%3A%(for clarity, I cut off
>>the end)
>>
>>The thing that sucks is I can't replicate this reliably.  I can hit reload
>>over and over, and it will only happen 1 out of every 10 or so times, on
>>random data coming back.  It's not just numerics, not text...
>>
>>I sniffed the connection, and here's one that barfed coming back from the
>>server:
>>
>>VALUE profile_1_7028277b0e9405414ea71de0bdde789f_rank 0 2\r\n-1\r\nEND\r\n
>>
>>Looks okay to me; it follows the protocol, and there are two characters in
>>the response.  Memcached isn't the culprit.  So on to the API...
>>
>>The problem appears to be with this line:
>>$line = substr($line, strpos($line, "\r\n")+1, strlen($line));
>>
>>I added some more logging lines before and after it to see what the 'pre'
>>and 'post' parsing results were.
>>
>>By only doing +1, you're just stripping off the \r.  It's always letting a
>>\n through, even though it should be stripping it off.  The strange thing to
>>me is sometimes it only lets a \n through, but sometimes it lets
>>"\n0\r\nEND\r\n" through (this is when it breaks).  I'm still trying to
>>track down why this is happening...
>>
>>In summary; I changed that +1 to a +2, and it always strips off the
>>remaining \n.  From there, it works great.  I just pushed about 300 pages,
>>and all came back without errors...
>>
>>Final patch:
>>==============
>>999c999
>><                                       $line = substr($line, strpos($line,
>>"\r\n")+1, strlen($line));
>>---
>>
>>>                                      $line = substr($line, strpos($line,
>>
>>"\r\n")+2, strlen($line));
>>===============
>>
>>"It works for me".  :)
>>
>>Justin
>>
>>----- Original Message -----
>>From: "Ryan Gilfether" <ryan@gilfether.com>
>>To: <memcached@lists.danga.com>
>>Sent: Monday, August 11, 2003 12:37 AM
>>Subject: Re: PHP API 1.0.7
>>
>>
>>
>>>yes, you're right, I didnt notice that a newline got included at the end
>>>of the file. I'll be sure to remove it in future releases. Thanks for
>>>pointing it out.
>>>
>>>Ryan
>>>
>>>Lisa Marie Seelye wrote:
>>>
>>>>On Sat, 2003-08-09 at 13:08, Ryan Gilfether wrote:
>>>>
>>>>
>>>>>A new version of the PHP API has been completed, verson 1.0.7.
>>>>>I've had some requests for adding PHPDocs style comments to the API.
>>>>>Along with that 3 new function have been added
>>>>>error() - returns an error code for the last error genterated
>>>>>error_string() - returns a string with a description of the error
>>>>>error_clear() - clears the last error
>>>>>
>>>>>Ryan
>>>>
>>>>
>>>>Not to be incredibly anal, but the .php file should not have any
>>>>newlines after the closing ?> tag -- this tends to mess with headers
>>>>should it be included after headers have been sent. :(
>>>>
>>>>
>>>
>>>--
>>>Ryan Gilfether
>>>Software Engineer
>>>http://www.gilfether.com
>>>
>>>
>>
>>
> 
> 

-- 
Ryan Gilfether
Software Engineer
http://www.gilfether.com

--------------020001090705080800040401
Content-Type: text/plain;
 name="php-memcached-1.0.8.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="php-memcached-1.0.8.diff"

--- devel/html/memcached/MemCachedClient.inc.php	2003-08-12 19:17:06.000000000 -0400
+++ MemCachedClient.inc.php	2003-08-11 00:27:44.000000000 -0400
@@ -602,7 +602,7 @@
 		}
 
 		// connect to the server, if it fails, add it to the host_dead below
-		$sock = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);
+		$sock = socket_create (AF_INET, SOCK_STREAM, getprotobyname("TCP"));
 
 		// we need surpress the error message if a connection fails
 		if(!@socket_connect($sock, $conn[0], $conn[1]))
@@ -996,7 +996,7 @@
 					$bytes_read = 0;
 
 					// get the left over data after the header is read
-					$line = substr($line, strpos($line, "\r\n")+2, strlen($line));
+					$line = substr($line, strpos($line, "\r\n")+1, strlen($line));
 				}
 				else
 				{

--------------020001090705080800040401--