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:
This is a duplicate of #52338.
Note that I partly disagree with the fix. Custom error handlers *can* check
error_reporting(), as illustrated in the example from
http://ca3.php.net/manual/en/function.set-error-handler.php
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting
return;
}
[...]
}
However, it would be rather inefficient if custom error handlers *should* (had
to) do that, in general. If that was the case, PHP should simply not call
user-defined error handlers when @ was used.
I think user-defined error handlers *should* do something like that, but only
in some cases.
Previous Comments:
------------------------------------------------------------------------
[2012-04-16 20:59:18] chealer at gmail dot com
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.
------------------------------------------------------------------------
[2012-04-16 20:39:54] [email protected]
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