Re: Howto use zend_register_functions ? possible bug with patch
| From: | Remi Collet | Date: | Mon, 02 Dec 2013 12:35:10 +0000 |
| Subject: | Re: Howto use zend_register_functions ? possible bug with patch | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-70467@lists.php.net to get a copy of this message | ||
Iterating on CG(function_table) instead of module.functions is a
possible fix.
Attached: rewrite of get_extension_funcs
Test:
foreach(get_loaded_extensions() as $ext) {
$a[$ext] = get_extension_funcs($ext);
}
print_r($a);
$ diff old new
+ [528] => dl
+ [529] => cli_set_process_title
+ [530] => cli_get_process_title
Minor change, when a extension replace a core function,
Ex: memprof use
const zend_function_entry memprof_function_overrides[] = {
PHP_FALIAS(memory_get_peak_usage, memprof_memory_get_peak_usage,
arginfo_memprof_memory_get_usage)
PHP_FALIAS(memory_get_usage, memprof_memory_get_usage,
arginfo_memprof_memory_get_usage)
PHP_FE_END /* Must be the last line in
memprof_function_overrides[] */
};
With this patch the "memory_get_peak_usage" will be reported as part of
"memprof" extension instead of "standard", but I think this seems also
correct (another effect of the bug)
Comments ?
Remi.
/* {{{ proto array get_extension_funcs(string extension_name) Returns an array with the names of functions belonging to the named extension */ ZEND_FUNCTION(get_extension_funcs) { char *extension_name, *lcname; int extension_name_len, array; zend_module_entry *module; HashPosition iterator; zend_internal_function *zif; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) { return; } if (strncasecmp(extension_name, "zend", sizeof("zend"))) { lcname = zend_str_tolower_dup(extension_name, extension_name_len); } else { lcname = estrdup("core"); } if (zend_hash_find(&module_registry, lcname, extension_name_len+1, (void**)&module) == FAILURE) { efree(lcname); RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator); if (module->functions) { /* avoid BC break, if functions list is empty, will return an empty array */ array_init(return_value); array = 1; } else { array = 0; } while (zend_hash_get_current_data_ex(CG(function_table), (void **) &zif, &iterator) == SUCCESS) { if (zif->module == module) { if (!array) { array_init(return_value); array = 1; } add_next_index_string(return_value, zif->function_name, 1); } zend_hash_move_forward_ex(CG(function_table), &iterator); } efree(lcname); if (!array) { RETURN_FALSE; } } /* }}} */
/* {{{ proto array get_extension_funcs(string extension_name) Returns an array with the names of functions belonging to the named extension */ ZEND_FUNCTION(get_extension_funcs) { char *extension_name, *lcname; int extension_name_len, array; zend_module_entry *module; HashPosition iterator; zend_internal_function *zif; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) { return; } if (strncasecmp(extension_name, "zend", sizeof("zend"))) { lcname = zend_str_tolower_dup(extension_name, extension_name_len); } else { lcname = estrdup("core"); } if (zend_hash_find(&module_registry, lcname, extension_name_len+1, (void**)&module) == FAILURE) { efree(lcname); RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator); if (module->functions) { /* avoid BC break, if functions list is empty, will return an empty array */ array_init(return_value); array = 1; } else { array = 0; } while (zend_hash_get_current_data_ex(CG(function_table), (void **) &zif, &iterator) == SUCCESS) { if (zif->module == module) { if (!array) { array_init(return_value); array = 1; } add_next_index_string(return_value, zif->function_name, 1); } zend_hash_move_forward_ex(CG(function_table), &iterator); } efree(lcname); if (!array) { RETURN_FALSE; } } /* }}} */