Bug #61747 [Nab]: User-defined error handler run despite at sign (@) error control operator

From: Date: Mon, 16 Apr 2012 20:59:18 +0000
Subject: Bug #61747 [Nab]: User-defined error handler run despite at sign (@) error control operator
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-169649@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=61747&edit=1

 ID:                 61747
 User updated by:    chealer at gmail dot com
 Reported by:        chealer at gmail dot com
 Summary:            User-defined error handler run despite at sign (@)
                     error control operator
 Status:             Not a bug
 Type:               Bug
 Package:            *General Issues
 PHP Version:        5.4.0
 Block user comment: N
 Private report:     N

 New Comment:

I'm sorry. This was fixed in http://svn.php.net/viewvc/phpdoc/en/trunk/language/operators.xml?r1=322134&r2=323370
We now have:

When prepended to an expression in PHP, any error messages that might be generated by that
expression will be ignored.

If you have set a custom error handler function with set_error_handler() then it will still get
called, but this custom error handler can (and should) call error_reporting() which will return 0
when the call that triggered the error was preceded by an @.


Note that this second sentence contradicts the first in some [edge] cases. At least, the second
sentence should immediately follow the first, rather than having its own paragraph.


Previous Comments:
------------------------------------------------------------------------
[2012-04-16 20:39:54] rasmus@php.net

The documentation is quite clear I think. In the first link you provided it 
says:

  If you have set a custom error handler function with set_error_handler() 
  then it will still get called, but this custom error handler can 
  (and should) call error_reporting() which will return 0 when the call 
  that triggered the error was preceded by an @.

I see no reason to change anything here. The current approach gives you all the 
control you need. If you have a custom error handler you can decide whether you 
want to ignore silenced calls or not. Any change to this would also be a major 
BC break.

------------------------------------------------------------------------
[2012-04-16 17:57:52] chealer at gmail dot com

Description:
------------
The at sign operator allows to "ignore" error messages, as explained in http://ca3.php.net/manual/en/language.operators.errorcontrol.php

When prepended to an expression in PHP, any error messages that might be generated by that
expression will be ignored. 

However, as reported in #61091, user-defined error handlers registered with set_error_handler() are
nevertheless run when @ is used, which often causes such messages to show, as in the below example,
where a custom error handler is used to customize the display of error messages.

As http://ca3.php.net/manual/en/language.operators.errorcontrol.php#98895
and http://ca3.php.net/manual/en/language.operators.errorcontrol.php#85042
show, this problem is not new. This behavior appears to be by design, and might be wanted in some
cases.

Therefore, please either:
Stop calling user-defined error handlers when suppressing errors. This needs serious consideration
for backwards-compatibility.
Allow specifying whether user-defined error handlers should be called when suppressing errors.
Make the documentation reflect the current state of things.

Alternatively, if the documentation of the @ operator isn't amended because custom error
handlers are considered a corner case, then the set_error_handler() documentation should warn
developers tempted to use custom error handlers that they are non-standard, not
recommended/supported, and try to explain the pitfalls. In short, tell developers they should only
use a custom error handler if they know what they're doing.

However, this alternative should be avoided since set_error_handler() is already used in several
applications whose developers didn't receive the warning.

Test script:
---------------
<?php

function myErrorHandler($errno, $errstr) {
    switch ($errno) {
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
        echo "  Fatal error on line $errline in file $errfile";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br
/>\n";
        echo "Aborting...<br />\n";
        exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
        break;

    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
        break;

    default:
        echo "Unknown error type: [$errno] $errstr<br />\n";
        break;
    }
}

// function to test the error handling
function scale_by_log($vect, $scale)
{
    if (!is_numeric($scale) || $scale <= 0) {
        trigger_error("log(x) for x <= 0 is undefined, you used: scale = $scale",
E_USER_ERROR);
    }

    if (!is_array($vect)) {
        trigger_error("Incorrect input vector, array of values expected", E_USER_WARNING);
        return null;
    }

    $temp = array();
    foreach($vect as $pos => $value) {
        if (!is_numeric($value)) {
            trigger_error("Value at position $pos is not a number, using 0 (zero)",
E_USER_NOTICE);
            $value = 0;
        }
        $temp[$pos] = log($scale) * $value;
    }

    return $temp;
}

$a = array(2, 3, "foo", 5.5, 43.3, 21.11);


/* Value at position $pos is not a number, using 0 (zero) */
scale_by_log($a, M_PI);
@scale_by_log($a, M_PI);

set_error_handler("myErrorHandler");
@scale_by_log($a, M_PI);

?>


Expected result:
----------------
Notice: Value at position 2 is not a number, using 0 (zero) in /var/www/atoperator.php on line 42

Call Stack:
    0.0005     339192   1. {main}() /var/www/atoperator.php:0
    0.0005     339836   2. scale_by_log(array (0 => 2, 1 => 3, 2 => 'foo', 3
=> 5.5, 4 => 43.3, 5 => 21.11), 3.1415926535898) /var/www/atoperator.php:55
    0.0006     340648   3. trigger_error('Value at position 2 is not a number, using 0
(zero)', 1024) /var/www/atoperator.php:42

Actual result:
--------------
Notice: Value at position 2 is not a number, using 0 (zero) in /var/www/atoperator.php on line 42

Call Stack:
    0.0005     339192   1. {main}() /var/www/atoperator.php:0
    0.0005     339836   2. scale_by_log(array (0 => 2, 1 => 3, 2 => 'foo', 3
=> 5.5, 4 => 43.3, 5 => 21.11), 3.1415926535898) /var/www/atoperator.php:55
    0.0006     340648   3. trigger_error('Value at position 2 is not a number, using 0
(zero)', 1024) /var/www/atoperator.php:42

<b>My NOTICE</b> [1024] Value at position 2 is not a number, using 0 (zero)<br />


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=61747&edit=1


Thread (13 messages)

« previous php.bugs (#169649) next »