# Getting global variable in a multithreaded PHP embedded application

- Thread: https://externals.io/message/27267
- Original archive: https://news-web.php.net/php.internals/27267
- Started by Roberto Fichera on 2007-01-05T09:25:37+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #27267 — Roberto Fichera — 2007-01-05T09:25:37+00:00

URL: https://externals.io/message/27267#27267

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.

---

## #27269 — Roberto Fichera — 2007-01-05T10:33:52+00:00

URL: https://externals.io/message/27267#27269 · In reply to: #27267

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. 
>
>-- 
>
>

Roberto Fichera.

---

## #27271 — johannes@php.net — 2007-01-05T11:18:10+00:00

URL: https://externals.io/message/27267#27271 · In reply to: #27269

Hi Roberto,


> 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
