# Issue with op_array moving

- Thread: https://externals.io/message/56786
- Original archive: https://news-web.php.net/php.internals/56786
- Started by James Edmunds on 2011-12-06T00:07:07+00:00
- Messages: 1
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #56786 — James Edmunds — 2011-12-06T00:07:07+00:00

URL: https://externals.io/message/56786#56786

Hi all,

I am writing an extension that does performance monitoring. I guess 
somewhat like xdebug but a bit different. The user can specify the 
functions / methods they care about and I will time the execution of those 
things. I do this by hooking zend_execute. My hook is:

void
rrdmon_execute (zend_op_array *op_array TSRMLS_DC)
{
...
}

After a php file has loaded ((op_array->function_name == NULL) && 
op_array->filename)) I check through the list of functions the user wants 
to monitor. I check to see if the thing they want to hook is a class or a 
normal function and then do something like this:

HashTable *ftbl = EG(function_table);
zend_function *func;

if (is_a_class_method) {
   zend_class_entry **ce;
   if (zend_hash_find (CG(class_table), classnm, classnmlen, (void **)&ce) 
== FAILURE) {
     return;
   }
   ftbl = &((*ce)->function_table);
}
if (zend_hash_find (ftbl, funcnm, funcnmlen, (void **)&func) == FAILURE) {
   return;
}

func->op_array.reserved[0] = pointer_to_my_stuff;

I dont actually use reserved[0] I do it properly getting the next offset 
but this was for illustrative purposes only.

Then in my rrdmon_execute I do something like:
if (op_array->reserved[0]) {
   ... do stuff ...;
}

This all works well, until I tried this with a class that had a namespace. 
The method is 
Symfony\Component\HttpKernel\Controller\ControllerResolver::getController.

It finds the class name (everything pre the ::) in CG(class_table) and it 
finds the function (getController) in that class's function table, but 
unlike every other class and function I have tested this with, the op_array 
that I put my stuff into isn't the one being executed. That is, 
func->op_array isn't the op_array that ends up getting passed to 
rrdmon_execute().

This seems to only be an issue with namespaces. Symfony does a bunch of 
weird caching stuff so the class gets loaded out of a cache file but at 
this level, that shouldn't matter.

So please, can someone who knows Zend's guts a bit better tell me if I am 
doing something wrong (this has worked just fine for several months up 
until I decided to time that stuff in Symfony which is the first time I 
have encountered namespaces) or if the op_array somehow gets moved around 
or how I should deal with namespaces for these purposes?

Any help greatly appreciated.

--Jim Edmunds.
