|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2003-05-13 21:26 UTC] ldemailly at qualys dot com
set_error_handler registered not called: very nasty/triky bug to nail/reproduce: I'm now at the point where if I try to minimize further the test scripts, the bug goes away: for instance, removing the "require q.inc" where q.inc is an empty file, or changing code that is *after* the offending code makes the bug go away (hides it), so I suspect some nasty problem in the engine, because it seems memory usage and/or complexity of the script to be parsed affects the outcome. to repro: copy paste, uudecode; gtar xvfz test_err.tgz cd test_err; php ErrorBug.php it will output "INSIDE test_should_error_out()" but not "ERROR HANDLER CALLED" as it should if you look at PHPUnit/TestCase.php line 158 and 147 the error is raised (as the Notice: Undefined variable: foo in /home/dl/dev/cvs/qualys/web/dev/current/internal/test_err/ErrorBug.php on line 7 demonstrates) but the handler is not called... if you edit BugTest1.php to remove the require 'q.inc' for instance, you will now see "ERROR HANDLER CALLED" even though q.inc is empty and should thus make no difference at all ! ps: the code has been modified from pear's phpunit module with a submitted patch for error handling; which works 'sometimes' (most of the time actually). in the tgz below, I removed a lot of stuff to make the files as small as possible... (incl headers/copyright notices, etc...)) I spent many many hours trying to narrow it down further (having a simpler script) but didn't manage, sorry for having a large set of files needed ... This is with the latest cvs (2003-05-13) on redhat linux 9 next message will be the .uu, if you're having any trouble, please email and I'll (re)send the repro scripts PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 00:00:02 2025 UTC |
Aha, I managed to reduce the repro script dramatically : <?php ini_set("error_reporting" , E_ALL); class TestErrorHdl { // Will not be called !! function errorHandler($errno, $errstr, $errfile, $errline) { echo("ERROR HANDLER CALLED (EXPECTED)\n"); } function runTest() { $res = set_error_handler(array(&$this, "errorHandler")); echo("set_error_handler done retcode=" . $res . "\n"); $bar = $foo; } } $t = new TestErrorHdl(); $t->runTest(); ?> --- output (buggy, with current 4.3 php cli versions): ---- $ php ErrorBug.php set_error_handler done retcode=1 Notice: Undefined variable: foo in /home/dl/test_err_tiny/ErrorBug.php on line 12 --- output (expected) : ---- set_error_handler done retcode=1 ERROR HANDLER CALLED (EXPECTED) [note that with a longer script it does *most of the time* work as expected, so it's not like the feature of having an instance method for a error handler is not supported at all...]A collegue of mine (Thanks Walter!) here actually found a fix (patch below); looking at the code it is puzzling that it would ever work, there seems to be some other bug/corruption in the zend engine that would explain why it works/ behave differently sometimes. Also that test for empty string should probably be before the test for callable... ? php-4.3.1-walt/Zend/zend_builtin_functions.c --- php-4.3.1/Zend/zend_builtin_functions.c 2002-11-27 12:11:10.000000000 -0800 +++ php-4.3.1-walt/Zend/zend_builtin_functions.c 2003-05-14 13:15:39.000000000 -0700 @@ -891,7 +891,8 @@ } ALLOC_ZVAL(EG(user_error_handler)); - if (Z_STRLEN_PP(error_handler)==0) { /* unset user-defined handler */ + /* Make sure we test for an empty string on a non-array value here */ + if (Z_TYPE_PP(error_handler) == IS_STRING && Z_STRLEN_PP(error_handler)==0) { /* unset user-defined handler */ FREE_ZVAL(EG(user_error_handler)); EG(user_error_handler) = NULL; RETURN_TRUE;I tested this with php 4.3.1 and found that the code assumes that what is passed in to set_error_handler() is a string, which you can clearly see by the line ... if (Z_STRLEN_PP(error_handler)==0) { /* unset user-defined ... This is wrong and does not work when you pass an array into set_error_handler( array(&$this, "myhandler") ); error_handler is an array zval, and therefore the test for Z_STRLEN_PP always returns 0. This case falls through and sets the user_error_handler = NULL; which prevents the user defined handler from working at all. I am able to reproduce this 100% of the time. Please fix this, as it is totally broken in its current state. The patch provided works. Also, if you assume that the variable passed in is a string, and happens to be empty, then why do we RETURN_TRUE; in that block, when in fact the user_error_handler is NOT set, and is set to NULL. This is also wrong. This is an error case which should return FALSE.sniper, what did you try exactly ? I tried again with the latest from cvs and ./configure --with-oci8=$ORACLE_HOME \ --with-apache=../../apache_1.3.27 --with-mcrypt=/usr/local \ --enable-sysvsem --enable-sysvshm --enable-trackvars \ --with-gd --with-png-dir=/usr \ --with-jpeg-dir=/usr --with-zlib-dir=/usr \ --with-mysql=/usr and from the command line : [dl@dl-pc php4]$ sapi/cli/php ~/foo.php set_error_handler done retcode=1 Notice: Undefined variable: foo in /home/dl/foo.php on line 12 This is another patch, as that unset thing seems to leave stuff corrupt and looks like dead code anyway (is_callable would theoritically fail for an empty string anyway) *** zend_builtin_functions.c.~1.124.2.4.~ 2002-12-31 08:22:58.000000000 -0800 --- zend_builtin_functions.c 2003-05-15 12:01:48.000000000 -0700 *************** *** 891,902 **** } ALLOC_ZVAL(EG(user_error_handler)); - if (Z_STRLEN_PP(error_handler)==0) { /* unset user-defined handler */ - FREE_ZVAL(EG(user_error_handler)); - EG(user_error_handler) = NULL; - RETURN_TRUE; - } - *EG(user_error_handler) = **error_handler; zval_copy_ctor(EG(user_error_handler)); --- 891,896 ---- with the patch : [dl@dl-pc php4]$ sapi/cli/php ~/foo.php set_error_handler done retcode= ERROR HANDLER CALLED (EXPECTED)