php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58493 memcache object loses port information
Submitted: 2009-01-06 18:50 UTC Modified: 2009-01-13 05:58 UTC
From: gotnew at yahoo dot com Assigned:
Status: Closed Package: memcache (PECL)
PHP Version: 5.2.5 OS: Ubuntu 8.04.1
Private report: No CVE-ID: None
 [2009-01-06 18:50 UTC] gotnew at yahoo dot com
Description:
------------
the memcache object will lose its port information the second time it access data or get status from Memcache server. This works with the previous 2.2.4 version.

And it also seems to work with Ubuntu 8.10.

Reproduce code:
---------------
<?php
$mc = new MemcachePool;
$mc->addServer("10.10.1.159", "11211");
$ss = $mc->getExtendedStats();
print_r($ss);

for ($i = 0; $i < 100; $i ++)
{
   sleep(1);
   $ss = $mc->getExtendedStats();
   print_r($ss);
}

?>

Expected result:
----------------
it should print out the server ip:port and the stats array.

Actual result:
--------------
the second time it prints the stats, the server's port number become 0. Notice the first time, it shows port number 11211, but from second time on, it shows 0.

Array
(
    [10.10.1.159:11211] => Array
        (
...omitted..
        )
)
Array
(
    [10.10.1.159:0] => Array
        (
...omitted...
        )
)




Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-08 14:49 UTC] mikael at synd dot info
Your script works fine for me, would you mind posting the memcache.* ini settings you're using (e.g. the memcache section in the phpinfo() output)?

I'm using PHP 5.2.8 and pecl/memcache 3.0.3-dev (i.e. from CVS)

It would also help a lot if you could find what specific conditions cause the problem, you say the Ubuntu 8.10 doesn't exhibit the problem but 8.04.1 does? So what's the difference between the two setups?
 [2009-01-08 15:18 UTC] gotnew at yahoo dot com
Thank you very much for your reply. Here's some output from phpInfo:

--------------------
PHP Version 5.2.4-2ubuntu5.4

memcache
memcache support	enabled
Version 	3.0.2
Revision 	$Revision: 1.83.2.28 $

Directive	Local Value	Master Value
memcache.allow_failover	1	1
memcache.chunk_size	32768	32768
memcache.default_port	11211	11211
memcache.hash_function	crc32	crc32
memcache.hash_strategy	consistent	consistent
memcache.max_failover_attempts	20	20
memcache.protocol	ascii	ascii
memcache.redundancy	1	1
memcache.session_redundancy	2	2
--------------------

This is how I installed memcache 3.0.2beta:

 sudo pecl install  http://pecl.php.net/get/memcache-3.0.2.tgz

How do I install the latest from CVS? Thanks.
 [2009-01-08 15:42 UTC] mikael at synd dot info
Hi,

The INI settings seem to be the default ones and the same as I was using. 

You can download and install pecl/memcache from CVS like

 cvs -d :pserver:cvsread@cvs.php.net:/repository checkout -r NON_BLOCKING_IO pecl/memcache
 phpize
 ./configure
 make && make install

Being unable to reproduce the problem there's really not much more I can do. If you can reliable reproduce the problem on Ubuntu 8.04.1 and not on 8.10 I'd recommend trying to find out what specific conditions cause the problem and I'll have a look at it again.

If you have programming experience you could also use a debugger (e.g. Eclipse/CDT) and "./configure --enable-debug" to compile a debug version and then run "php /path/to/your/script.php" under Eclipse to try and figure out what the problem is (we're always happy when people provide us with patches along with the bug reports :)
 [2009-01-08 15:44 UTC] mikael at synd dot info
There should also be be a "cd pecl/memcache" before "phpize" in the build instructions, like

 cvs ..
 cd pecl/memcache
 phpize

And remove the linebreak from the cvs command..
 [2009-01-08 19:07 UTC] gotnew at yahoo dot com
I got the latest code from CVS and built it and ran my script on the command line (not under Eclipse or something), I still have the same error.

I did turn on enable-debug, where would I see the debug message?
 [2009-01-09 20:27 UTC] gotnew at yahoo dot com
FYI, I verified that it works with php 5.2.6 and 5.2.8 but it showed the problem I originally reported with php 5.2.4.
 [2009-01-12 21:18 UTC] ryanobjc at gmail dot com
The problem is a memory stomp in memcache_pool.c.  The offending line is:

       if (!io->stream || php_stream_cast(io->stream, PHP_STREAM_AS_FD_FOR_SELECT, (void **)&(io->fd), 1) != SUCCESS) {

Which looks fine, until you realize that on platforms where sizeof(void**) == 8 and sizeof(int) (the declared type on io->fd which is of struct type mmc_stream_t) == 4.  The relevant part of the struct is:

struct mmc_stream {
	php_stream	*stream;
	int		fd;
	unsigned short     port;
/* rest of struct elided */
}

So the very next struct element gets overwritten.  Here is the GDB trace showing the memory stomp in action:

(gdb) print *mmc
$18 = {tcp = {stream = 0xddee60, fd = 0, port = 11211, chunk_size = 32768, status = 0, 
    failed = 0, retry_interval = 15, buffer = {value = {c = 0x0, len = 0, a = 0}, idx = 0}, 
    read = 0, readline = 0, input = {value = '\0' <repeats 4095 times>, idx = 0}}, udp = {
    stream = 0x0, fd = 0, port = 0, chunk_size = 32768, status = 0, failed = 0, 
    retry_interval = 15, buffer = {value = {c = 0x0, len = 0, a = 0}, idx = 0}, read = 0, 
    readline = 0, input = {value = '\0' <repeats 4095 times>, idx = 0}}, sendreq = 0x0, 
  readreq = 0x0, buildreq = 0x0, sendqueue = {items = 0x0, alloc = 0, head = 0, tail = 0, 
    len = 0}, readqueue = {items = 0x0, alloc = 0, head = 0, tail = 0, len = 0}, 
  host = 0xddc820 "10.10.1.159", timeout = 1, persistent = 1, reqid = 0, error = 0x0, 
  errnum = 0}
(gdb) n
695		php_stream_set_option(io->stream, PHP_STREAM_OPTION_BLOCKING, 0, NULL);
(gdb) print *mmc
$19 = {tcp = {stream = 0xddee60, fd = 5, port = 0, chunk_size = 32768, status = 0, 
    failed = 0, retry_interval = 15, buffer = {value = {c = 0x0, len = 0, a = 0}, idx = 0}, 
    read = 0, readline = 0, input = {value = '\0' <repeats 4095 times>, idx = 0}}, udp = {
    stream = 0x0, fd = 0, port = 0, chunk_size = 32768, status = 0, failed = 0, 
    retry_interval = 15, buffer = {value = {c = 0x0, len = 0, a = 0}, idx = 0}, read = 0, 
    readline = 0, input = {value = '\0' <repeats 4095 times>, idx = 0}}, sendreq = 0x0, 
  readreq = 0x0, buildreq = 0x0, sendqueue = {items = 0x0, alloc = 0, head = 0, tail = 0, 
    len = 0}, readqueue = {items = 0x0, alloc = 0, head = 0, tail = 0, len = 0}, 
  host = 0xddc820 "10.10.1.159", timeout = 1, persistent = 1, reqid = 0, error = 0x0, 
  errnum = 0}


As you can see immediately after that line, port now = 0.

A patch that fixes this looks like:
===================================================================
RCS file: /repository/pecl/memcache/Attic/memcache_pool.c,v
retrieving revision 1.1.2.32
diff -u -r1.1.2.32 memcache_pool.c
--- memcache_pool.c     8 Jan 2009 21:56:17 -0000       1.1.2.32
+++ memcache_pool.c     13 Jan 2009 02:13:56 -0000
@@ -677,8 +677,9 @@
                efree(hash_key);
        }
 
+       void *fd;
        /* check connection and extract socket for select() purposes */
-       if (!io->stream || php_stream_cast(io->stream, PHP_STREAM_AS_FD_FOR_SELECT, (void **)&(io->fd), 1) != SUCCESS) {
+       if (!io->stream || php_stream_cast(io->stream, PHP_STREAM_AS_FD_FOR_SELECT, &fd, 1) != SUCCESS) {
                mmc_server_seterror(mmc, errstr != NULL ? errstr : "Connection failed", errnum);
                mmc_server_deactivate(pool, mmc TSRMLS_CC);
 
@@ -688,7 +689,7 @@
 
                return MMC_REQUEST_FAILURE;
        }
-
+       io->fd = (int)fd;
        io->status = MMC_STATUS_CONNECTED;
 
        php_stream_auto_cleanup(io->stream);


This fix should also work on 32 bit compiles... But I didn't test it. 

The patch fixes the problems we're seeing.  I hope this can be included post-haste.  

To be clear: this bug will only affect 64 bit compiles.
 [2009-01-13 05:58 UTC] mikael at synd dot info
This bug has been fixed in CVS.

In case this was a documentation problem, the fix will show up at the
end of next Sunday (CET) on pecl.php.net.

In case this was a pecl.php.net website problem, the change will show
up on the website in short time.
 
Thank you for the report, and for helping us make PECL better.

Thanks for the patch! Don't have a 64-bit system to test on..
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Apr 29 16:01:31 2024 UTC