Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
base system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
6 Sep 2008 at 22:37 UTC
Updated:
28 Jun 2010 at 20:36 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
damien tournoud commentedTest results with this patch: we have hidden failures (ie. errors or exceptions that occurs during the test but are not caught by assertions)
Comment #2
damien tournoud commentedA while(true) loop made chx cringe. Here is a refactoring (thanks, chx).
Comment #3
pwolanin commentedDoing a quick visual patch review - this looks odd to me:
Also looks like debug code left in index.php:
Comment #4
damien tournoud commented@pwolanin: the same function is used as both and error_handler() and an exception_handler(). The signature of those function are different but most of the processing is common.
Comment #5
damien tournoud commentedThe same patch without the
if (func_num_args() == 5)and the debugging code.Comment #6
damien tournoud commentedI'm marking this as postponed, until #305077: Rework simpletest backend is in.
Comment #7
damien tournoud commentedComment #8
damien tournoud commentedThis is a patch based on #305077: Rework simpletest backend, that draft how this could look like. DrupalTestBod will be angry, but I don't care :p
Comment #11
damien tournoud commentedComment #12
damien tournoud commentedHere is a first patch for the exception handler. I separated the simpletest part in another patch to ease review.
This patch refactors drupal_error_handler, implements an exception handler and reimplement the backtracing feature we had for database functions.
Also fixes a small bug in _drupal_get_last_caller(): if PHP generates an error in an internal function (like strpos, for example), no line information is available for the last call of the stack.
Comment #13
catchInstalled this on a clean HEAD. Tested by going to admin/content/taxonomy/edit/term/ which handily produces many different notices and warnings at the moment, then messed with a couple of db_query() to add syntax errors. Seems pretty good to me, and I like the way the eventual simpletest handling will go to. I also did a visual review of the patch, and although there's one existing long array of error codes which could be split across lines, that was the only thing I could find to gripe about. And no test breakage.
Could do with another look over it, but nice work.
Comment #14
chx commentedWhile catch is right about that array needig better indents it's more important to use PHP E_ constants. Speaking of constants, there are more and more with every PHP release, so $types[$errno] can be nothing. This needs handling.
"Errors that occurs" that's "occur".
Comment #15
damien tournoud commentedReroll, addressing chx' concerns.
Comment #16
Crell commentedSubscribe.
Comment #17
damien tournoud commentedRerolled following #308399: The simpletest error handler is broken for PHP functions.
Comment #18
Anonymous (not verified) commentedpatch at #17 applies cleanly, and all tests pass. looks RTBC to me.
Catch notices, warnings, errors and fatal errors from the tested side is now waiting on this patch.
Comment #19
webchick1. Yay for replacing obscure numbers with actual error constants. But let's add a comment that explains where these come from.
2. Should we add in an update function for this? It seems that changing the case will affect the ability to filter log messages, no?
3. These are not wrapped in t(). Is that by design?
@param $exception needs documentation. What type of exception is that? Is that coming from PHP or us?
Dear, sweet, merciful crap! ;) Is there any way to break that up and make it more legible? I'd be more in favour of 3-level nesting than a 15-condition while statement.
1. Capital U on uncaught, for consistency with the rest.
2. Comment above here to explain how we get here. Is this normal, or is it weird?
PHPDoc please.
Comment #20
damien tournoud commented1. Done
2. Not needed.
The "Type" is always "php". We always considered PHP errors to be of severity WATCHDOG_ERROR. The patch doesn't change this.
3. This is by design. The error message itself can't be translated (it comes from PHP), and I don't like the idea of half-translated messages.
Moreover implementing this cleanly (ie. messages output to the users have to be translated, but not those going to the watchdog that should be dynamic, etc.) would probably add lots of ugly lines of code to the patch (ie. one watchdog call per $type, *sigh*).
I documented both _drupal_error_handler and _drupal_exception_handler, and marked those as private.
While grepping through the core, I also found a DB:TNG left-over in database.inc.
This is not for everyone's eyes. It took time to cleanly engineer this one. It would make no real sense to break the condition out of the where (the loop is guaranteed to terminate only because of the array_shift inside it). Why and what is done is clearly documented above the loop, so I'm no willing to touch this again.
1. Well caught (:p).
2. I augmented the documentation of _drupal_exception_handler to clearly indicate that it is always fatal to have uncaught exceptions.
Done.
Comment #21
drewish commentedsubscribing. ran all the tests and this doesn't affect them (there's two problem with node tests regardless of this patch). visually it looks good to me.
Comment #22
c960657 commentedThe term "error_reporting" is currently used to for specifying whether errors should be displayed to the user (0 = Hide errors, 1 = Show errors - see system_error_reporting_settings()). The patch uses the same term in name of the variable that contains the PHP error level (i.e. one of the E_xxx constants). I think one of these should be renamed in order to avoid confusion between the two unrelated concepts. I suggest renaming the existing setting to "display_errors" to be in sync with the corresponding php.ini setting.
+ _drupal_log_error(isset($types[$errno]) ? $types[$error_level] : 'Unknown error', $message, $backtrace);$errno is not defined at this point. Looks like a left-over from the renaming of $errno to $error_level.
E_STRICT is not part of E_ALL (only in PHP ≥ 6), so AFAICT the string is never used, so I think it should be omitted.
How about changing
if ($errno & (E_ALL)) {toif ($errno & error_reporting()) {to allow users use more verbose error reporting than E_ALL (e.g. E_ALL ¦ E_STRICT)? If we do that, we should probably reseterror_reportingto E_ALL in .htaccess and/or in bootstrap.inc - but before settings.php is included.In preparation for PHP 5.3, we might want to add E_DEPRECATED and E_USER_DEPRECATED as well (I have heard about early adopters running their own builds of PHP 5.3 or even PHP 6). The constants are not defined in PHP 5.2.x, so if we choose to support them, we should either use their numerical values or define them using define().
+ watchdog('php', '%error: %message in %function (line %line of %file).', array('%error' => $type, '%message' => $message, '%function' => $caller['function'], '%file' => $caller['file'], '%line' => $caller['line']), WATCHDOG_ERROR);For greater readability I suggest replacing
%errorwith%type. There is no need to introduce another word for the same concept.The error handler appears to assume that the error message, $message, is plain text. But if the
html_errorsPHP ini setting is enabled,$messagecontains HTML tags that are check_plain'ed before being output, making the messages hard to read. I don't mind dropping support forhtml_errors, i.e. making Drupal callini_set('html_errors', '0')somewhere, but I don't know whether anybody would miss this feature. Comment #7 on issue 313902 includes a patch that disabledhtml_errors.The PHP manual says:
It is not specific about when it is necessary, but I assume they refer to E_USER_ERROR and E_RECOVERABLE_ERROR errors (there are other fatal error types, but these cannot be caught using a custom error handler). I suggest handling these like uncaught exceptions.
If an exception is somehow thrown during bootstrapping (e.g. try to insert
throw new Exception('foo');in common.inc right after the exception handler has been set), the exception handler dies with this error:Fatal error: Call to undefined function user_access() in /home/c960657/www/drupal/includes/theme.inc on line 1752I don't know whether exceptions are likely to be raised during phase of the bootstrap, though.
+ if (variable_get('error_level', 1) == 1 || strstr($_SERVER['SCRIPT_NAME'], 'update.php')) {Wouldn't it be better to use the MAINTENANCE_MODE constant?
I know many of the issues mentioned are also present in the existing code. But now that we are touching the code, I think it is a good time to discuss them.
Comment #23
damien tournoud commentedHere is a new version, addressing most of c960657's concerns:
- corrected typo with $errno
- complied with error_reporting level, a sane default is now set in settings.php, but could be overridden by the user
- added an ini_set('html_errors', 0) to settings.php
- output an error page in case of an RECOVERABLE_ERROR (poor choice of name for fatal errors that can still launch an error handler), for consistency with exceptions
- fix the output of the error page in probably pretty much every case (including during the bootstrap), do not show blocks on the error page for consistency with 404/403 pages.
Comment #24
damien tournoud commentedThe default.settings.php chunk didn't make it inside the patch... Anyway it makes much more sense to set sane default in drupal_initialize_variables(), before settings.php is called.
Comment #25
damien tournoud commented@c960657: your other suggestions (especially adding E_DEPRECATED) are to big for this, and could be discussed in another issue.
Comment #26
moshe weitzman commentedWhat is the best way to test that this is working as designed?
Comment #27
webchickYeah, I'd like to know that as well.
If you're going to force E_ALL at all times, why bother with the if()? And if you're bothering with the if() do you need one around ini_set() too?
I'm kinda -1 this code generally, but I'm fine putting it in until we can do better at #291026: change E_NOTICE to warning and allow selection of error level.
I understand renaming drupal_error_handler and _drupal_exception_handler to make them private, since that's very unlikely to be called outside of common.inc. However is _drupal_log_error() also an internal-only function, or is that something other modules might trigger?
Finally, I would really like to see some tests for at least that tweaky PDOException stuff. That seems like the perfect example of something someone well meaning is going to easily break somewhere along the line trying to "fix" it. Also, then Moshe wouldn't have to ask questions like "What is the best way to test that this is working as designed?" ;)
Nitpick time!
a) there should be a newline between the description and the param list.
b) The description here and others in this docblock need to be indented one space.
Please rephrase so it fits in < 80 characters.
Overall though, this patch is a huge improvement, and I can't wait to press the big green button on it. :D
Comment #28
dries commentedPersonally, I don't like the fact that we have to threat PDOExceptions special. Where will this end? We can't special-case for every possible exception.
I didn't remember what html_errors was for so I had to look it up. Would be great if you could improve that code-comment a bit.
Comment #29
damien tournoud commentedI now changed that logic to a clearer (and saner):
There is now an unit test.
(That's such a pain to write, I hate you guys.)
Sincerely, me neither. But (1) we did that before for database errors, (2) we have no other choice (because PHP is limited).
I would rather keep that private. Do you have an use case for calling that directly?
Comment #30
lilou commented@damien : in function testErrorHandler(),
Comment #31
damien tournoud commentedRemoved the redundant assertion, thanks lilou.
Comment #32
Crell commentedFor the record, I hate the special case handling for database errors. I'm very open to better handling of that, although probably in a separate patch.
Comment #33
mfer commentedTests ran without error. On a brief code review it looks good. I agree with Dries and Crell on the PDOexception special case. It's not pretty.
Comment #34
moshe weitzman commentedThis patch was very helpful to me when debugging a PDO Exception. Without it, I had no meaningfull error message at all. I can't really comment on the particulars, but I can say that we need something like this. It appears to me that the PDO handling just restores what we have in D6 and thus should not hold up the patch.
Comment #35
damien tournoud commentedA new version, with a cleaner test (we no longer need to instrument _drupal_log_error, and we can remove a lot of lines of code).
Comment #36
catchI can't get all tests to run with or without this patch, which is a shame. I ran the exception tests though, and manually generated some errors (notices in eval()ed code, fatal errors in node.module etc.) and it caught them all nicely. Also reviewed comments and stuff with Damien in irc.
While the crazy while loop and PDO specific stuff aren't nice, nor's not being able to show exceptions etc. in simpletests.
Comment #37
Anonymous (not verified) commentedall tests pass for me with patch #35 on a fresh HEAD - looks RTBC.
Comment #38
gpk commented@damien: I'm hardly in a position to offer an authoritative opinion, but looks a great patch to me. :D
@all: Also for the record (and a separate patch) - is it time to add support for error/exception handling in hook_boot/exit after a cached response? In the case of hook_exit() you may never see the error, unless you keep an eye on the Apache error log. moshe's comment #34 emphasises the potential value of this.
Comment #39
dries commentedAfter another review of this patch, I committed it to CVS HEAD. I do get one exception and one error when running the tests, but it does not seem related to this patch itself. I'll investigate that separately. Thanks Damien.
Comment #40
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #41
Pedro Lozano commentedI miss it, a lot!
Now when I'm developing and things crash instead of getting a nice xdebug backtrace I get a bunch of ugly unformatted text. And there is no benefit, it crashes miserably and drupal is not able to do anything about it.
You should not force people to use a php settings if it's not for security reasons.
Comment #42
berdirI've never seen an incompatibility between xdebug and Drupal 7 since Drupal catches exceptions and displays them with the maintenance theme unless they happen *very* early.