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