On Fri, Sep 18, 2020 at 7:02 AM Alexander Mashin <alex.mas...@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 >