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