Dear all,
I am trying to make a PHP (7.4) extension use in an extension method a
setting from php.ini (like myext.map=key1=val1,key2=val2;) parsed as an
associative array. I want the parsing to happen in PHP_MINIT_FUNCTION(myext)
.
So, I declared a php setting, uncommented REGISTER_INI_ENTRIES(); in
PHP_MINIT_FUNCTION(myext), declared:
ZEND_BEGIN_MODULE_GLOBALS(myext)
HashTable map;
ZEND_END_MODULE_GLOBALS(myext)
and filled MYEXT_G(map) from the php.ini settingJR:
PHP_INI_MH(myext_update_map) {// The part that parses new_value into
(key => val) pairs is skipped. It works.//...// key = val assignments
have been counted.
zend_hash_init(&MYEXT_G(map), count, NULL, NULL, 1); // 1 for
"persistent".// ...// Iterating (key => value) pairs.
// key, key_len, val, val_len have been successfully extracted from php.ini.
zend_string * key_z = zend_string_init( key, key_len, 1 );
zval val_z;
ZVAL_STRINGL( &val_z, val, val_len );
zend_hash_add_new( &MYEXT_G(map), key_z, &val_z );
Then, in a PHP method, I try to read data from &MYEXT_G(map):
PHP_METHOD(MyExt, getMap) {// ...
zend_string * key_z;
zval * val_z;
ZEND_HASH_FOREACH_STR_KEY_VAL(&MYEXT_G(map), key_z, val_z)
php_error_docref( NULL
TSRMLS_CC, E_WARNING, "ZSTR_VAL(key_z) =
%s\n", ZSTR_VAL(key_z) );
php_error_docref( NULL
TSRMLS_CC, E_WARNING, "Z_STRVAL_P(val_z) =
%s\n", Z_STRVAL_P(val_z) );
php_error_docref( NULL
TSRMLS_CC, E_WARNING, "Z_STRLEN_P(val_z) =
%lu\n", Z_STRLEN_P(val_z) );
ZEND_HASH_FOREACH_END();
If the PHP script containing MyExt::getLibraries() is called from the
command line, the PHP warnings print keys and values as they were set in
php.ini.
However, if the script is called by HTTP request, in the warning messages,
ZSTR_VAL(key_z) is correct but both Z_STRVAL_P(val_z) and Z_STRLEN_P(val_z)
contain garbage.
All involved functions are either defined as PHP macros or receive TSRMLS_DC
.
It seems that the values (but not keys) in a global hashtable get
deallocated between module initialisation and serving HTTP request.
I have made sure that scalar values in MYEXT_G survive from
PHP_MINIT_FUNCTION(myExt) into PHP method called from HTTP request.
So, how can I make sure that HashTable values are really persistent?
Alexander Mashin
On Fri, Sep 18, 2020 at 7:02 AM Alexander Mashin alex.mashin@gmail.com
wrote:
Dear all,
I am trying to make a PHP (7.4) extension use in an extension method a
setting from php.ini (like myext.map=key1=val1,key2=val2;) parsed as an
associative array. I want the parsing to happen in
PHP_MINIT_FUNCTION(myext)
.So, I declared a php setting, uncommented REGISTER_INI_ENTRIES(); in
PHP_MINIT_FUNCTION(myext), declared:ZEND_BEGIN_MODULE_GLOBALS(myext)
HashTable map;
ZEND_END_MODULE_GLOBALS(myext)and filled MYEXT_G(map) from the php.ini settingJR:
PHP_INI_MH(myext_update_map) {// The part that parses new_value into
(key => val) pairs is skipped. It works.//...// key = val assignments
have been counted.
zend_hash_init(&MYEXT_G(map), count, NULL, NULL, 1); // 1 for
"persistent".// ...// Iterating (key => value) pairs.
// key, key_len, val, val_len have been successfully extracted from
php.ini.
zend_string * key_z = zend_string_init( key, key_len, 1 );
zval val_z;
ZVAL_STRINGL( &val_z, val, val_len );
zend_hash_add_new( &MYEXT_G(map), key_z, &val_z );
ZVAL_STRINGL allocates a per-request string. You'll want to use
ZVAL_STR(&val_z, zend_string_init(val, val_len, 1)); or so.
Nikita
Then, in a PHP method, I try to read data from &MYEXT_G(map):
PHP_METHOD(MyExt, getMap) {// ...
zend_string * key_z;
zval * val_z;
ZEND_HASH_FOREACH_STR_KEY_VAL(&MYEXT_G(map), key_z, val_z)
php_error_docref(NULL
TSRMLS_CC, E_WARNING, "ZSTR_VAL(key_z) =
%s\n", ZSTR_VAL(key_z) );
php_error_docref(NULL
TSRMLS_CC, E_WARNING, "Z_STRVAL_P(val_z) =
%s\n", Z_STRVAL_P(val_z) );
php_error_docref(NULL
TSRMLS_CC, E_WARNING, "Z_STRLEN_P(val_z) =
%lu\n", Z_STRLEN_P(val_z) );
ZEND_HASH_FOREACH_END();If the PHP script containing MyExt::getLibraries() is called from the
command line, the PHP warnings print keys and values as they were set in
php.ini.However, if the script is called by HTTP request, in the warning messages,
ZSTR_VAL(key_z) is correct but both Z_STRVAL_P(val_z) and Z_STRLEN_P(val_z)
contain garbage.All involved functions are either defined as PHP macros or receive
TSRMLS_DC
.It seems that the values (but not keys) in a global hashtable get
deallocated between module initialisation and serving HTTP request.I have made sure that scalar values in MYEXT_G survive from
PHP_MINIT_FUNCTION(myExt) into PHP method called from HTTP request.So, how can I make sure that HashTable values are really persistent?
Alexander Mashin