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
>

Reply via email to