Hi,
I'm working on PHP7 compatibility for an extension (which I didn't write).
I discovered an issue with a call like this:
call_user_function_ex(EG(function_table), NULL, zval, &retval, 5, params,
0, NULL);
When zval refers to a [object, string] array, its value is different after
this call. I haven't seen this issue when zval is a string. I realize the
context probably matters here, but I'm having trouble narrowing down what
could be doing this. Any suggestions on how to debug this?
Thanks,
Adam
Hi Adam,
Adam Baratz wrote:
I'm working on PHP7 compatibility for an extension (which I didn't write).
I discovered an issue with a call like this:call_user_function_ex(EG(function_table), NULL, zval, &retval, 5, params,
0, NULL);When zval refers to a [object, string] array, its value is different after
this call. I haven't seen this issue when zval is a string. I realize the
context probably matters here, but I'm having trouble narrowing down what
could be doing this. Any suggestions on how to debug this?
The function which handles going from a "callable" zval to an actual
zend_function pointer is zend_is_callable_ex in Zend/zend_API.c, and I
imagine that's where the problem lies.
Perhaps it's a reference-counting/copy-on-write issue?
Hope this helps!
Andrea Faulds
http://ajf.me/
Hi,
Le 17/12/2015 22:52, Adam Baratz a écrit :
Hi,
I'm working on PHP7 compatibility for an extension (which I didn't write).
I discovered an issue with a call like this:call_user_function_ex(EG(function_table), NULL, zval, &retval, 5, params,
0, NULL);When zval refers to a [object, string] array, its value is different after
this call. I haven't seen this issue when zval is a string. I realize the
context probably matters here, but I'm having trouble narrowing down what
could be doing this. Any suggestions on how to debug this?Thanks,
Adam
If your code is public, can you give a pointer to the problematic call ?
Or at least what your 'zval' points to on return.
Regards
François
If your code is public, can you give a pointer to the problematic call ?
Or at least what your 'zval' points to on return.
It's the PECL memcache extension:
https://pecl.php.net/package/memcache
All of the existing test suite passes, except for this one:
http://git.php.net/?p=pecl/caching/memcache.git;a=blob;f=tests/033.phpt;h=dad8214786d909fbce5bc6a1b4fd69b59daf5c79;hb=HEAD
It verifies an error callback mechanism using a few different styles of
callbacks. I've trimmed the test down to the first string-based case and
that works fine. I get a segfault when I focus on the "OO callback" case.
This is where the callback is invoked:
http://git.php.net/?p=pecl/caching/memcache.git;a=blob;f=memcache.c;h=6a7576d1a86fdbeaf8f30c3cfd54ac642719c006;hb=HEAD#l1096
Reference counting appears to be in order. See mmc_server_callback_ctor()
and mmc_server_callback_dtor() for where that happens. PHP7 compatible
versions of those functions don't look very different, nor does most of the
surrounding code. The main changes I had to make to the extension involved
handling resource zvals.
Entering the call_user_function_ex() call, the callback array has a ref
count of 1 and its 0th element has a count of 2 (according to gdb). The
same is true when I run the test with PHP56. The value of the array zval
changes inside the call to call_user_function_ex(), in a call to
zend_vm_stack_push_call_frame() (determined via setting a watch). It ends
up with garbage contents (its type is not a defined value).
Let me know if there's any other info I can dig up.
Thanks,
Adam