php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #57562 Problem with "callback function" on addServer method
Submitted: 2007-03-06 09:21 UTC Modified: 2007-03-06 12:48 UTC
From: basilio dot vera at softonic dot com Assigned:
Status: Closed Package: memcache (PECL)
PHP Version: 4.4.2 OS: Linux RHLE4
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: basilio dot vera at softonic dot com
New email:
PHP Version: OS:

 

 [2007-03-06 09:21 UTC] basilio dot vera at softonic dot com
Description:
------------
Incompatibility detected when using an user error handler and one "failure callback" method is used inside the addServer() method.

The static call is OK, but not bypassing the real object. This really works on another places!

Reproduce code:
---------------
<?php
function user_error_handler( $severity, $msg, $filename, $linenum ) {
	if (ini_get('error_reporting') & $severity) {
		$date	= date('Y-m-d H:i:s');
		$stack_error = debug_backtrace(); unset($stack_error[0]); // Without GLOBALS/_ENV/_SERVER... (too many info!)
		$debug = '';
		foreach($stack_error as $stack_num => $stack_step) {
			$debug .= "#$stack_num: File {$stack_step['file']}, line {$stack_step['line']}, function {$stack_step['function']}";
			if ( isset( $stack_step['args'] ) && count( $stack_step['args'] ) ) $debug .= ", args: ".implode( ', ', $stack_step['args'] );
			$debug .= "<br />\n";
		}
		echo <<<ERROR_STRING
<span>[$date] {$errType[$severity]}: <b>$msg</b> in <b>$filename</b> on line <b>$linenum</b></span><br />
$debug--------------<br />
ERROR_STRING;
	}
}

set_error_handler( 'user_error_handler' );

trigger_error( 'TEST', E_USER_WARNING );

$memcache_profile['name'] = 'production';
$memcache_profile['servers'][0]['host'] = 'mem1';		$memcache_profile['servers'][0]['port'] = 11211;
$memcache_profile['servers'][1]['host'] = 'error_test';	$memcache_profile['servers'][1]['port'] = 11211;

class memcached {
	var $memcache;
	var $profile;

	function memcached($profile) {
		$this->profile	= $profile;

		$this->memcache = new Memcache;
		foreach($profile['servers'] as $servers) {
			$this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1, 20, true, array(&$this, 'raise_error'));
		}
	}

	function get($key) {
		return $this->memcache->get($key);
	}

	function set($key, $var, $expire = 0) {
		return $this->memcache->set($key, $var, MEMCACHE_COMPRESSED, $expire);
	}

	function raise_error($host, $port) {
		trigger_error( "MEMCACHE: Server error. Profile: '{$this->profile['name']}' Host: '$host' Port: '$port'", E_USER_WARNING );
	}
}
$memcache = &new memcached( $memcache_profile );
$memcache->set( 'key1', 'test key 1' );
$memcache->set( 'key2', 'test key 2' );
echo $memcache->get( 'key2' );
?>

Expected result:
----------------
[2007-03-06 15:19:17] : TEST in /home/basilio.vera/test/test_error_memcache.php on line 22
#1: File /home/basilio.vera/test/test_error_memcache.php, line 22, function trigger_error, args: TEST, 512
--------------
[2007-03-06 15:19:17] : set(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in /home/basilio.vera/test/test_error_memcache.php on line 46
#1: File /home/basilio.vera/test/test_error_memcache.php, line 46, function set, args: key1, test key 1, 2, 0
#2: File /home/basilio.vera/test/test_error_memcache.php, line 54, function set, args: key1, test key 1
--------------
[2007-03-06 15:19:17] : MEMCACHE: Server error. Profile: 'production' Host: 'error_test' Port: '11211' in /home/basilio.vera/test/test_error_memcache.php on line 50
#1: File /home/basilio.vera/test/test_error_memcache.php, line 50, function trigger_error, args: MEMCACHE: Server error. Profile: 'production' Host: 'error_test' Port: '11211', 512
#2: File , line , function raise_error, args: error_test, 11211
#3: File /home/basilio.vera/test/test_error_memcache.php, line 46, function set, args: key1, test key 1, 2, 0
#4: File /home/basilio.vera/test/test_error_memcache.php, line 54, function set, args: key1, test key 1
--------------
test key 2

Actual result:
--------------
VOID -- NOTHING!! but... If I change the "function callback"...

$this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1, 20, true, array(&$this, 'raise_error'));

For this:

$this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1, 20, true, array('memcached', 'raise_error'));

The error handler acts, but I can't get the profile attribute... :(

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-03-06 09:38 UTC] tony2001 at phpclub dot net
Please provide short (~20 lines max) reproduce case.
And please specify which PECL/memcache version you're using.
 [2007-03-06 09:45 UTC] basilio dot vera at softonic dot com
<?php
function user_error_handler( $severity, $msg, $filename, $linenum ) {
	print_r(debug_backtrace());
}
set_error_handler( 'user_error_handler' ); trigger_error( 'TEST', E_USER_WARNING );
$memcache_profile['name'] = 'production';
$memcache_profile['servers'][0]['host'] = 'mem1';		$memcache_profile['servers'][0]['port'] = 11211;
$memcache_profile['servers'][1]['host'] = 'error_test';	$memcache_profile['servers'][1]['port'] = 11211;
class memcached {
	var $memcache;	var $profile;
	function memcached($profile) {
		$this->profile	= $profile;	$this->memcache = new Memcache;
		foreach($profile['servers'] as $servers) $this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1, 20, true, array('memcached', 'raise_error'));
	}
	function get($key) { return $this->memcache->get($key);	}
	function set($key, $var, $expire = 0) {	return $this->memcache->set($key, $var, MEMCACHE_COMPRESSED, $expire);}
	function raise_error($host, $port) { trigger_error( "MEMCACHE: Server error. Profile: '{$this->profile['name']}' Host: '$host' Port: '$port'", E_USER_WARNING ); }
}
$memcache = &new memcached( $memcache_profile ); $memcache->set( 'key1', 'test key 1' ); $memcache->set( 'key2', 'test key 2' ); echo $memcache->get( 'key2' );
?>
 [2007-03-06 09:49 UTC] basilio dot vera at softonic dot com
Sorry, I forgot the PECL memcache version: 2.1.0
 [2007-03-06 10:26 UTC] tony2001 at phpclub dot net
What are the actual and expected results of this code?
 [2007-03-06 10:54 UTC] basilio dot vera at softonic dot com
Sorry, I'll edit the issue again.
 [2007-03-06 11:13 UTC] basilio dot vera at softonic dot com
OK, I'try it again...

Description:
------------
Incompatibility detected when one
"failure callback" method is used inside the addServer() method.

The static call is OK, but not bypassing the real object. This really
works on another places!

Reproduce code:
---------------
<?php
$memcache_profile['name'] = 'production';
$memcache_profile['servers'][0]['host'] = 'mem1'; $memcache_profile['servers'][0]['port'] = 11211;
$memcache_profile['servers'][1]['host'] = 'error_test'; $memcache_profile['servers'][1]['port'] = 11211;
class memcached {
	var $memcache;
	var $profile;
	function memcached($profile) {
		$this->profile	= $profile; $this->memcache = new Memcache;
		foreach($profile['servers'] as $servers) $this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1, 20, true, array(&$this, 'raise_error'));
	}
	function get($key) { return $this->memcache->get($key); }
	function set($key, $var, $expire = 0) { return $this->memcache->set($key, $var, MEMCACHE_COMPRESSED, $expire); }
	function raise_error($host, $port) { trigger_error( "MEMCACHE: Server error. Profile: '{$this->profile['name']}' Host: '$host' Port: '$port'", E_USER_WARNING ); }
}
trigger_error( 'TEST', E_USER_WARNING );
$memcache = &new memcached( $memcache_profile ); $memcache->set( 'key1', 'test key 1' ); $memcache->set( 'key2', 'test key 2' ); echo $memcache->get( 'key2' );
?>

Expected:
--------

Warning: TEST in /home/basilio.vera/test/test_error_memcache.php on line 16

Warning: set(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in /home/basilio.vera/test/test_error_memcache.php on line 13

Warning: MEMCACHE: Server error. Profile: 'production' Host: 'error_test' Port: '11211' in /home/basilio.vera/test/test_error_memcache.php on line 14
test key 2

Actual result:
-------------
NOTHING!!!

But if I change the addServer method from this: -> array(&$this, 'raise_error')

$this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1,
20, true, array(&$this, 'raise_error'));

to this -> array('memcached', 'raise_error') [called statically]

$this->memcache->addServer($servers['host'], $servers['port'], 0, 10, 1,
20, true, array('memcached', 'raise_error'));

I get:


Warning: TEST in /home/basilio.vera/test/test_error_memcache.php on line 16

Warning: set(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in /home/basilio.vera/test/test_error_memcache.php on line 13

Warning: MEMCACHE: Server error. Profile: '' Host: 'error_test' Port: '11211' in /home/basilio.vera/test/test_error_memcache.php on line 14
test key 2
 [2007-03-06 12:46 UTC] tony2001 at phpclub dot net
Your code is not going to work as is.
Using $this as the callback means adding a reference to $this to $this->memcache.
So you have the eternal chicken-and-egg problem here:
$this => $this->memcache => $this.
Don't do that.

The segfault should be fixed in CVS, though.
 [2007-03-06 12:48 UTC] tony2001 at phpclub dot net
Also please, next time don't reduce the code removing new lines =)
It doesn't become shorter, but becomes completely unreadable. 50% of your reproduce code can be safely dropped in order to prepare really short reproduce code.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Dec 27 19:01:28 2024 UTC