Getting global variable in a multithreaded PHP embedded application

php.internals

Roberto Fichera

19 years ago
Hi All, I'm just new to php embed application but I'm at good point after some work/fighting with the engine API. My intention is to run different php scripts in a multithreaded application at the same time. Furthermore I don't need to make some php intercomunications and/or parallel script exection. So, the approch I follow, for embedding the PHP in to my application, is the usual (I guess ;-) sapi with some other hints from the plpgsql, PHP-Interpreter source codes. So I initialize the php engine with: int initEngine( void ) { zend_compiler_globals *compiler_globals; zend_executor_globals *executor_globals; php_core_globals *core_globals; sapi_globals_struct *sapi_globals; void ***tsrm_ls; if ( ze_started == true ) { return 0; } if ( !tsrm_startup( 128, 32, TSRM_ERROR_LEVEL_CORE, "/tmp/TSRM.log") ) { ANY_LOG( 0, "Unable to init the PHP TSRM!", ANY_LOG_FATAL ); return -1; } /* get some globals from the PHP engine */ compiler_globals = ts_resource( compiler_globals_id ); executor_globals = ts_resource( executor_globals_id ); core_globals = ts_resource( core_globals_id ); sapi_globals = ts_resource( sapi_globals_id ); tsrm_ls = ts_resource( 0 ); HSI_sapi.php_ini_path_override = "/etc/php.ini"; sapi_startup( &HSI_sapi ); ze_started = true; if ( php_module_startup( &HSI_sapi, NULL, 0 ) == FAILURE ) { ANY_LOG( 0, "Failed to initialize PHP", ANY_LOG_FATAL ); return -1; } } while each context is allocated by the follow: void *createInterpreter( void ) { void *interp = NULL; void *prev_interp = NULL; interp = tsrm_new_interpreter_context(); prev_interp = tsrm_set_interpreter_context( interp ); { TSRMLS_FETCH(); zend_alter_ini_entry("register_argc_argv", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_alter_ini_entry("implicit_flush", 15, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); SG( headers_sent ) = 1; SG( request_info ).no_headers = 1; SG( options ) = SAPI_OPTION_NO_CHDIR; php_request_startup( TSRMLS_C ); PG( during_request_startup ) = 0; tsrm_set_interpreter_context( prev_interp ); } return( interp ); } my scripts are evalutated with: bool phpEval( void *interp, char *cmd, zval *zv ) { bool retVal = true; void *prev_interp = NULL; prev_interp = tsrm_set_interpreter_context( interp ); { TSRMLS_FETCH(); zend_try { if ( zend_eval_string( cmd, zv, "PHP Embedded Interface" TSRMLS_CC ) == FAILURE ) { fprintf( stderr, "Unable to send the command '%s' on Php", cmd ); retVal = false; goto out; } } zend_catch { fprintf( stderr, "Unable to send the command '%s' on Php", cmd ); retVal = false; goto out; } zend_end_try() { } } out: tsrm_set_interpreter_context( prev_interp ); return( retVal ); } so now the question is, since I execute each php script in a different context how can I get global variables from it? I tried to use the code below but it doesn't work. Obviously the zend_hash_find( &EG(symbol_table) ... ) works great in a "standard" application using the macros PHP_EMBED_START/END_BLOCK(argc,argv): zval **data = NULL; HashTable *arrayHash = NULL; void *prev_interp = NULL; prev_interp = tsrm_set_interpreter_context( self->interp ); { TSRMLS_FETCH(); if ( zend_hash_find( &EG(symbol_table), "myVar", sizeof( "myVar" ), (void **)&data) == FAILURE ) { fprintf( stderr, "The infoString array myVar not found in $GLOBALS" ); goto out; } if ( data == NULL ) { fprintf( stderr, "myVar doesn't contains any data" ); goto out; } } out: tsrm_set_interpreter_context( prev_interp ); I guess that the EG(symbol_table) isn't correct here but I don't find any place where to clarify how to get global variables from a given context. Does anyone can explain me how to do it? Thanks in advance. Roberto Fichera.

Roberto Fichera

19 years ago
At 10.25 05/01/2007, you wrote:
>Hi All, > >I'm just new to php embed application but I'm at good point >after some work/fighting with the engine API. My intention is >to run different php scripts in a multithreaded application at the >same time. Furthermore I don't need to make some php >intercomunications and/or parallel script exection. So, the approch >I follow, for embedding the PHP in to my application, is the usual >(I guess ;-) sapi with some other hints from the plpgsql, PHP-Interpreter >source codes. So I initialize the php engine with: > >int initEngine( void ) >{ > zend_compiler_globals *compiler_globals; > zend_executor_globals *executor_globals; > php_core_globals *core_globals; > sapi_globals_struct *sapi_globals; > void ***tsrm_ls; > > if ( ze_started == true ) > { > return 0; > } > > if ( !tsrm_startup( 128, 32, TSRM_ERROR_LEVEL_CORE, "/tmp/TSRM.log") ) > { > ANY_LOG( 0, "Unable to init the PHP TSRM!", ANY_LOG_FATAL ); > return -1; > } > > /* get some globals from the PHP engine */ > compiler_globals = ts_resource( compiler_globals_id ); > executor_globals = ts_resource( executor_globals_id ); > core_globals = ts_resource( core_globals_id ); > sapi_globals = ts_resource( sapi_globals_id ); > tsrm_ls = ts_resource( 0 ); > > HSI_sapi.php_ini_path_override = "/etc/php.ini"; > > sapi_startup( &HSI_sapi ); > > ze_started = true; > > if ( php_module_startup( &HSI_sapi, NULL, 0 ) == FAILURE ) > { > ANY_LOG( 0, "Failed to initialize PHP", ANY_LOG_FATAL ); > return -1; > } >} > >while each context is allocated by the follow: > >void *createInterpreter( void ) >{ > void *interp = NULL; > void *prev_interp = NULL; > > interp = tsrm_new_interpreter_context(); > > prev_interp = tsrm_set_interpreter_context( interp ); > { > TSRMLS_FETCH(); > > zend_alter_ini_entry("register_argc_argv", 19, "0", 1, >PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); > zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, >PHP_INI_STAGE_ACTIVATE); > zend_alter_ini_entry("implicit_flush", 15, "1", 1, PHP_INI_SYSTEM, >PHP_INI_STAGE_ACTIVATE); > zend_alter_ini_entry("max_execution_time", 19, "0", 1, >PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); > > SG( headers_sent ) = 1; > SG( request_info ).no_headers = 1; > SG( options ) = SAPI_OPTION_NO_CHDIR; > > php_request_startup( TSRMLS_C ); > > PG( during_request_startup ) = 0; > > tsrm_set_interpreter_context( prev_interp ); > } > > return( interp ); >} > >my scripts are evalutated with: > >bool phpEval( void *interp, char *cmd, zval *zv ) >{ > bool retVal = true; > void *prev_interp = NULL; > > prev_interp = tsrm_set_interpreter_context( interp ); > { > TSRMLS_FETCH(); > > zend_try > { > if ( zend_eval_string( cmd, zv, "PHP Embedded Interface" >TSRMLS_CC ) == FAILURE ) > { > fprintf( stderr, "Unable to send the command '%s' on Php", cmd ); > retVal = false; > goto out; > } > } > zend_catch > { > fprintf( stderr, "Unable to send the command '%s' on Php", cmd ); > retVal = false; > goto out; > } > zend_end_try() > { > } > } > > out: > tsrm_set_interpreter_context( prev_interp ); > > return( retVal ); >} > >so now the question is, since I execute each php script in a different context >how can I get global variables from it? I tried to use the code below >but it doesn't >work. Obviously the zend_hash_find( &EG(symbol_table) ... ) works great in a >"standard" application using the macros PHP_EMBED_START/END_BLOCK(argc,argv): > > zval **data = NULL; > HashTable *arrayHash = NULL; > void *prev_interp = NULL; > > prev_interp = tsrm_set_interpreter_context( self->interp ); > { > TSRMLS_FETCH(); > > if ( zend_hash_find( &EG(symbol_table), "myVar", sizeof( "myVar" >), (void **)&data) == FAILURE ) > { > fprintf( stderr, "The infoString array myVar not found in $GLOBALS" ); > goto out; > } > > if ( data == NULL ) > { > fprintf( stderr, "myVar doesn't contains any data" ); > goto out; > } > } > > out: > tsrm_set_interpreter_context( prev_interp ); > >I guess that the EG(symbol_table) isn't correct here but I don't find >any place >where to clarify how to get global variables from a given context. >Does anyone can >explain me how to do it?
I found the solution myself :-))!! Basically using the active_symbol_table instead of the symbol_table and adding +1 to the sizeof(), I solved the problem :-))!!! zval **data = NULL; HashTable *arrayHash = NULL; void *prev_interp = NULL; prev_interp = tsrm_set_interpreter_context( self->interp ); { TSRMLS_FETCH(); if ( zend_hash_find( EG(active_symbol_table), "myVar", sizeof( "myVar" )+1, (void **)&data) == FAILURE ) { fprintf( stderr, "The infoString array myVar not found in $GLOBALS" ); goto out; } if ( data == NULL ) { fprintf( stderr, "myVar doesn't contains any data" ); goto out; } } out: tsrm_set_interpreter_context( prev_interp ); Now my problem is how to find declared functions in a context. Which hash table I have to use?
> >Thanks in advance. > >Roberto Fichera. > >-- >PHP Internals - PHP Runtime Development Mailing List >To unsubscribe, visit: http://www.php.net/unsub.php
Roberto Fichera.

Johannes Schlueter

19 years ago
Hi Roberto, On Fri, 2007-01-05 at 11:33 +0100, Roberto Fichera wrote:
> Now my problem is how to find declared functions in a context. Which hash table > I have to use?
Just take a look at the structure behind the executor_globals EG struct: http://lxr.php.net/source/ZendEngine2/zend_globals.h#147 to see which HashTable might contain the function_table. In that structure you might find other useful elements )(maybe you need the class table or constants table, too?) ;-) johannes

Roberto Fichera

19 years ago
At 12.18 05/01/2007, Johannes Schlüter wrote:
>Hi Roberto, > >On Fri, 2007-01-05 at 11:33 +0100, Roberto Fichera wrote: >> Now my problem is how to find declared functions in a context. Which >hash table >> I have to use? > >Just take a look at the structure behind the executor_globals EG struct: >http://lxr.php.net/source/ZendEngine2/zend_globals.h#147 to see which >HashTable might contain the function_table. In that structure you might >find other useful elements )(maybe you need the class table or constants >table, too?) ;-)
Yep! I tried to following code but it seems not working as expected. I don't know also if the "data" is declared correctly but the zend_hash_find() returns FAILURE. int main( int argc, char *argv[] ) { zend_file_handle script; zval **data = NULL; script.type = ZEND_HANDLE_FP; script.filename = ( argc > 1 ? argv[1] : "test.php" ); script.opened_path = NULL; script.free_filename = 0; script.handle.fp = fopen( script.filename, "rb" ); PHP_EMBED_START_BLOCK(argc,argv) zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, &script); if ( zend_hash_find( EG(function_table), "myFunc", sizeof( "myFunc" )+1, (void **)&data) == FAILURE ) { fprintf( stderr, "%s(): Name not found\n", __func__ ); return -1; } if ( data == NULL ) { fprintf( stderr, "%s(): Value is NULL\n", __func__ ); return -1; } fprintf( stderr, "The function 'myFunc' has been found\n" ); PHP_EMBED_END_BLOCK() return 0; }
> >johannes > >-- >PHP Internals - PHP Runtime Development Mailing List >To unsubscribe, visit: http://www.php.net/unsub.php
Roberto Fichera.

Roberto Fichera

19 years ago
At 12.33 05/01/2007, Roberto Fichera wrote:
>At 12.18 05/01/2007, Johannes Schlüter wrote: > >>Hi Roberto, >> >>On Fri, 2007-01-05 at 11:33 +0100, Roberto Fichera wrote: >>> Now my problem is how to find declared functions in a context. Which >>hash table >>> I have to use? >> >>Just take a look at the structure behind the executor_globals EG struct: >>http://lxr.php.net/source/ZendEngine2/zend_globals.h#147 to see which >>HashTable might contain the function_table. In that structure you might >>find other useful elements )(maybe you need the class table or constants >>table, too?) ;-) > >Yep! I tried to following code but it seems not working as expected. I >don't know >also if the "data" is declared correctly but the zend_hash_find() >returns FAILURE.
Below there's the script with the correct func_ptr pointer for the zend_hash_find() but indeed still not working for me ;-)! test.php function myFunc() { echo "Hello"; } #include <php_embed.h> int main( int argc, char *argv[] ) { zend_file_handle script; zend_function *func_ptr = NULL; script.type = ZEND_HANDLE_FP; script.filename = ( argc > 1 ? argv[1] : "test.php" ); script.opened_path = NULL; script.free_filename = 0; script.handle.fp = fopen( script.filename, "rb" ); PHP_EMBED_START_BLOCK(argc,argv) zend_execute_scripts( ZEND_REQUIRE TSRMLS_CC, NULL, 1, &script ); if ( zend_hash_find( EG( function_table ), "myFunc", sizeof( "myFunc" ), (void **)&func_ptr) == FAILURE ) { fprintf( stderr, "%s(): Name not found\n", __func__ ); return -1; } if ( func_ptr == NULL ) { fprintf( stderr, "%s(): Value is NULL\n", __func__ ); return -1; } fprintf( stderr, "The function 'myFunc' has been found\n" ); PHP_EMBED_END_BLOCK() return 0; }
> >int main( int argc, char *argv[] ) >{ > zend_file_handle script; > zval **data = NULL; > > script.type = ZEND_HANDLE_FP; > script.filename = ( argc > 1 ? argv[1] : "test.php" ); > script.opened_path = NULL; > script.free_filename = 0; > script.handle.fp = fopen( script.filename, "rb" ); > > PHP_EMBED_START_BLOCK(argc,argv) > > zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, &script); > > if ( zend_hash_find( EG(function_table), "myFunc", sizeof( >"myFunc" )+1, (void **)&data) == FAILURE ) > { > fprintf( stderr, "%s(): Name not found\n", __func__ ); > return -1; > } > > if ( data == NULL ) > { > fprintf( stderr, "%s(): Value is NULL\n", __func__ ); > return -1; > } > > fprintf( stderr, "The function 'myFunc' has been found\n" ); > > PHP_EMBED_END_BLOCK() > > return 0; >} > > > >> >>johannes
Roberto Fichera.

Roberto Fichera

19 years ago
At 13.05 05/01/2007, Roberto Fichera wrote:
>At 12.33 05/01/2007, Roberto Fichera wrote: >>At 12.18 05/01/2007, Johannes Schlüter wrote: >> >>>Hi Roberto, >>> >>>On Fri, 2007-01-05 at 11:33 +0100, Roberto Fichera wrote: >>>> Now my problem is how to find declared functions in a context. Which >>>hash table >>>> I have to use? >>> >>>Just take a look at the structure behind the executor_globals EG struct: >>>http://lxr.php.net/source/ZendEngine2/zend_globals.h#147 to see which >>>HashTable might contain the function_table. In that structure you might >>>find other useful elements )(maybe you need the class table or constants >>>table, too?) ;-) >> >>Yep! I tried to following code but it seems not working as expected. I >>don't know >>also if the "data" is declared correctly but the zend_hash_find() >>returns FAILURE. > >Below there's the script with the correct func_ptr pointer for the >zend_hash_find() >but indeed still not working for me ;-)!
I found the problem :-))))!!! The solution was to specify the function name in lower case!!!! So replacing the "myFunc" with "myfunc" works as expected!!!! And now I'm able to call the requested function from a thread :-)))!!!
> >test.php >function myFunc() >{ > echo "Hello"; >} > > >#include <php_embed.h> > >int main( int argc, char *argv[] ) >{ > zend_file_handle script; > zend_function *func_ptr = NULL; > > script.type = ZEND_HANDLE_FP; > script.filename = ( argc > 1 ? argv[1] : "test.php" ); > script.opened_path = NULL; > script.free_filename = 0; > script.handle.fp = fopen( script.filename, "rb" ); > > PHP_EMBED_START_BLOCK(argc,argv) > > zend_execute_scripts( ZEND_REQUIRE TSRMLS_CC, NULL, 1, &script ); > > if ( zend_hash_find( EG( function_table ), "myFunc", sizeof( >"myFunc" ), (void **)&func_ptr) == FAILURE ) > { > fprintf( stderr, "%s(): Name not found\n", __func__ ); > return -1; > } > > if ( func_ptr == NULL ) > { > fprintf( stderr, "%s(): Value is NULL\n", __func__ ); > return -1; > } > > fprintf( stderr, "The function 'myFunc' has been found\n" ); > > PHP_EMBED_END_BLOCK() > > return 0; >} > >> >>int main( int argc, char *argv[] ) >>{ >> zend_file_handle script; >> zval **data = NULL; >> >> script.type = ZEND_HANDLE_FP; >> script.filename = ( argc > 1 ? argv[1] : "test.php" ); >> script.opened_path = NULL; >> script.free_filename = 0; >> script.handle.fp = fopen( script.filename, "rb" ); >> >> PHP_EMBED_START_BLOCK(argc,argv) >> >> zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, &script); >> >> if ( zend_hash_find( EG(function_table), "myFunc", sizeof( >>"myFunc" )+1, (void **)&data) == FAILURE ) >> { >> fprintf( stderr, "%s(): Name not found\n", __func__ ); >> return -1; >> } >> >> if ( data == NULL ) >> { >> fprintf( stderr, "%s(): Value is NULL\n", __func__ ); >> return -1; >> } >> >> fprintf( stderr, "The function 'myFunc' has been found\n" ); >> >> PHP_EMBED_END_BLOCK() >> >> return 0; >>} >> >> >> >>> >>>johannes > > >Roberto Fichera. > >-- >PHP Internals - PHP Runtime Development Mailing List >To unsubscribe, visit: http://www.php.net/unsub.php
Roberto Fichera.