From:             wharmby at uk dot ibm dot com
Operating system: Windows XP 
PHP version:      4CVS-2006-11-02 (snap)
PHP Bug Type:     Scripting Engine problem
Bug description:  Unnecessary calls to OnModify callback routine for an 
extension INI directive

Description:
------------
Unnecessary calls to OnModify callback routine for an
extension INI directives in ZTS enabled builds.

Please note the problem reported here only applies to ZTS 
enabled builds.

I have tried the supplied testcase on the latest snap-shot 
build for Windows (Nov 2, 2006 09:30 GMT)and the problem 
persists. phpinfo() shows "PHP Version => 5.2.1-dev".

Problem also persists in latest checked in version of file 
in CVS.

If I define a OnMOdify callback routine for an extension INI
directive the routine is called multiple times during
startup even though the directive is not being continually
modified. I expected one call as a result of modification to
the directive in php.ini but instead I got 3 calls.

I spotted this behaviour reviewing the engine code whilst 
reading Sara Golemon's book "Extending and Embedding PHP" 
and include a slightly modified version of sample code
from her book to illustrate the unnecessary calls.

The first problem is that in a ZTS enabled build 
zend_ini_refresh_caches() is called twice for each new 
thread. The method zend_new_thread_end_handler() calls it 
directly as follows: 

static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC)
{
    zend_copy_ini_directives(TSRMLS_C);
    zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC);
}

However, zend_copy_ini_directives() itself also calls
zend_ini_refresh_caches() so we end up calling any OnModifty callback
routines twice for each new thread.

I believe that: 
   (1) the call in zend_copy_ini_directives() can safely be
       removed, and 
   (2) the call in zend_new_thread_end_handler() should
       really be conditional on the success of the copy 
       operation, otherwise we could attempt to iterate
       over a non-existent hash and die. 

This will reduce the number of calls to 2 on ZTS emabled builds but any
OnModifycallback routine will still be called twice on the startup thread
in ZTS enabled builds; once by zend_register_ini_entries() during MINIT
processing when an extension registers its INI directives and again on
ZTS
builds during zend_post_startup() processing, i.e 

 zend_post_startup() -> zend_new_thread_end_handler()  -> 
 zend_ini_refresh_caches()

Whilst the call to the OnModify callback routine from
zend_register_ini_entries() is required for non-ZTS builds 
to work correctly I can see no need for a call from 
zend_ini_refresh_caches() during zend_post-startup 
processing. I believe this can easily be resolved by 
modifying zend_post_startup() to call 
      zend_copy_ini_directives() 
instead of 
      zend_new_thread_end_handler()

My patch for zend.c is here: http://pastebin.ca/234196
and for zend_ini.c here: http://pastebin.ca/234200 


Reproduce code:
---------------
Reproduce code is here: http://pastebin.ca/234201

I tested by adding the following to php.ini:

sample4.greeting="Hello Andy"

or via command line as:

-dsample4.greeting="Hello Andy"

Expected result:
----------------
When running using CLI on Windows, i.e a ZTS enabled build, I 
expected to see 1 call to my extensions "OnModify" callback 
routine for each thread attached; so in this simple case I expected to see
just the 1 call as follows:

>> sample 4: thread 0xfbc minit
sample 4: thread 0xfbc greeting modified..new value is Hello Andy
<< sample 4: thread 0xfbc minit
Hello Andy


Actual result:
--------------
The OnModify call back routine is in fact called 3 times; once
during MINIT processing and twice further. These last 2 are during the
call to zend_new_thread-end_handler().

>> sample 4: thread 0x16f8 minit
sample 4: thread 0x16f8 greeting modified..new value is Hello Andy
<< sample 4: thread 0x16f8 minit
sample 4: thread 0x16f8 greeting modified..new value is Hello Andy
sample 4: thread 0x16f8 greeting modified..new value is Hello Andy
Hello Andy




-- 
Edit bug report at http://bugs.php.net/?id=39344&edit=1
-- 
Try a CVS snapshot (PHP 4.4): 
http://bugs.php.net/fix.php?id=39344&r=trysnapshot44
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=39344&r=trysnapshot52
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=39344&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=39344&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=39344&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=39344&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=39344&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=39344&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=39344&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=39344&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=39344&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=39344&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=39344&r=globals
PHP 3 support discontinued:   http://bugs.php.net/fix.php?id=39344&r=php3
Daylight Savings:             http://bugs.php.net/fix.php?id=39344&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=39344&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=39344&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=39344&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=39344&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=39344&r=mysqlcfg

Reply via email to