|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-05-05 11:30 UTC] abodera at gmail dot com
Description:
------------
Running the following piece of code on 5.3.2 will cause a segfault under CLI. It will also kill an apache child with "zend_mm_heap corrupted" written into error_log.
Of course this code should be avoided (there is no real need for such double instantiation of the same connection), but it happened in my application and caused a lot of trouble before pinpointed.
The problem does NOT occur with the same SVN version of memcached + PHP 5.2.9, so I'd say it's >5.3 specific. Also, it's probably easy to solve, as multiple calls with the same connection id should return the same resource.
Also: Thanks for great extension! :)
A.
Reproduce code:
---------------
<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
$m = new Memcached('test');
if(!count($m->getServerList())){
$m->addServer('127.0.0.101',11211);
$m->addServer('127.0.0.102',11211);
}
$m = new Memcached('test');
if(!count($m->getServerList())){
$m->addServer('127.0.0.101',11211);
$m->addServer('127.0.0.102',11211);
}
Actual result:
--------------
CLI: segmentation fault
apache2: zend_mm_heap corrupted
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 05:00:01 2025 UTC |
No problems here jared@ubuntu:~$ cat bug.php <?php error_reporting(E_ALL); ini_set('display_errors',1); $m = new Memcached('test'); if(!count($m->getServerList())){ $m->addServer('127.0.0.101',11211); $m->addServer('127.0.0.102',11211); } $m = new Memcached('test'); if(!count($m->getServerList())){ $m->addServer('127.0.0.101',11211); $m->addServer('127.0.0.102',11211); } jared@ubuntu:~$ php bug.php jared@ubuntu:~$ php -v PHP 5.3.2 (cli) (built: May 3 2010 17:24:22) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies jared@ubuntu:~$ cd Desktop/php-memcached/ && git rev-parse HEAD && cd ../.. 19b048921d6ac15e83cfd8c091e5d0a43c4078d8 jared@ubuntu:~$ uname -a Linux ubuntu 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:09:38 UTC 2010 x86_64 GNU/LinuxI am still seeing this connection issue with the code from GitHub. # php -i | fgrep -C 2 "memcached support" memcached memcached support => enabled Version => 2.0.0-dev libmemcached version => 0.39 <?php $pid = getmypid(); for($x=0;$x<20;$x++) { $mc = new Memcached("test"); $mc->addServer("localhost", 11211); $mc->get("foo"); unset($mc); $connections = trim(`lsof -n -p $pid | fgrep -c "11211"`); $mem = trim(`fgrep VmRSS /proc/$pid/status`); echo "$x: $connections conns, $mem\n"; } ?> This outputs: # php memcached.php 0: 1 conns, VmRSS: 10400 kB 1: 2 conns, VmRSS: 10420 kB 2: 2 conns, VmRSS: 10424 kB 3: 2 conns, VmRSS: 10432 kB 4: 2 conns, VmRSS: 10436 kB 5: 3 conns, VmRSS: 10444 kB 6: 3 conns, VmRSS: 10452 kB 7: 4 conns, VmRSS: 10464 kB 8: 4 conns, VmRSS: 10468 kB 9: 4 conns, VmRSS: 10472 kB 10: 5 conns, VmRSS: 10484 kB 11: 6 conns, VmRSS: 10492 kB 12: 6 conns, VmRSS: 10496 kB 13: 6 conns, VmRSS: 10504 kB 14: 6 conns, VmRSS: 10504 kB 15: 7 conns, VmRSS: 10512 kB 16: 7 conns, VmRSS: 10516 kB 17: 7 conns, VmRSS: 10524 kB 18: 8 conns, VmRSS: 10532 kB 19: 8 conns, VmRSS: 10536 kBBased on what is in github, it looks like the user land best practice is this: $servers = array( array( "host" => "localhost", "port" => 11211, "weight" => 1 ), array( "host" => "localhost", "port" => 11211, "weight" => 2 ), array( "host" => "localhost", "port" => 11211, "weight" => 3 ), ); $mc = new Memcached("test"); if($mc->isPristine()){ $server_list = $mc->getServerList(); if($server_list != $servers){ $server_keys = array(); foreach($server_list as $sl){ $key = $sl["host"].':'.$sl["port"].':'.$sl["weight"]; $server_keys[$key] = true; } foreach($servers as $s){ $key = $s["host"].':'.$s["port"].':'.$s["weight"]; if(!isset($server_keys[$key])){ $mc->addServer($s["host"], $s["port"], $s["weight"]); } } } } OR: $mc = new Memcached("test"); if($mc->isPristine()){ foreach($servers as $s){ $mc->addServer($s["host"], $s["port"], $s["weight"]); } } The first method could lead to server lists varying across nodes if code roll out is not handled well to different servers. But, I am wondering if we can just get one of these two logics added to the addServer and addServers methods and not have to do it in user space.In fact, here is a patch for the simplest of the methods. diff --git a/php_memcached.c b/php_memcached.c index 1323d5e..3072817 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1619,6 +1619,11 @@ PHP_METHOD(Memcached, addServer) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; + if(!i_obj->is_pristine) { + RETURN_TRUE; + } + + if (host[0] == '/') { /* unix domain socket */ status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); } else { @@ -1653,6 +1658,10 @@ PHP_METHOD(Memcached, addServers) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; + if(!i_obj->is_pristine) { + RETURN_TRUE; + } + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(servers)), i = 0; zend_hash_get_current_data(Z_ARRVAL_P(servers), (void **)&entry) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(servers)), i++) {