Closed (duplicate)
Project:
Drupal core
Version:
8.0.x-dev
Component:
dblog.module
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
21 Mar 2012 at 16:51 UTC
Updated:
29 Jul 2014 at 20:30 UTC
Jump to comment: Most recent file
Comments
Comment #1
pfournier commentedSorry, incorrect patch. Here is the right one.
Comment #2
pfournier commentedThere should really be a way to replace attached files :-)
Comment #3
filijonka commentedI've not read the patch but for me this sounds like a strange idea; it's better to make a patch to the module that is where the error is.
Comment #4
pfournier commentedYou are right.
However, it is a bad thing that dblog becomes inaccessible because of a wrong call to watchdog(). dblog should protect itself from this.
Comment #5
pillarsdotnet commentedSeems like the protection should happen before serializing rather than after unserializing (i.e. on store rather than on retrieve).
Comment #6
pfournier commented@pillarsdotnet: I thought about that, and I hesitated between the two fixes.
I decided to do the check on output because it could happen that some nasty module writes directly in the watchdog table. Doing the check on the output catches more possible errors.
Comment #7
pfournier commentedComment #8
pillarsdotnet commentedThen it should check *both* places, for paranoia's sake.
Also, two tests should be written:
Comment #10
adharris commentedThe attached contains the tests suggested in #1492898-8: A bad call to watchdog() should not break the error logging system..
Case 1 creates a watchdog call using
watchdog('module_name', 'Error', WATCHDOG_ERROR);, and then selects the message back from the database and asserts that the variables field in the database is a serialized php.Case 2 manually inserts a record into {watchdog} with intentionally bad data. Then the admin/reports/dblog is checked to make sure there is no error.
I think we came up with fixes for both cases. Case 2 is covered by the patch in #1492898-2: A bad call to watchdog() should not break the error logging system.. Case 2 is fixed in
dblog_watchdogby checking if the passed variables value is an array or null before inserting into the database. If a non-null non-array value is passed, it is wrapped in an array before being saved to the database.We're not sure of the reason for the need to check that variables is not null for case 2, but other dblog tests fail without it. It would probably be good to get some more eyes on that to make sure it's the right solution.
Thanks to greengurl and simplicitymetrics for their contribution on this.
Comment #11
adharris commentedAfter a bit more discussion at the drupalcon sprint, I'm pretty sure this is something that shouldn't be fixed. I'll attempt to explain the reasoning:
The central issue is is the bad call to watchdog.
watchdog('module_name', 'Error', WATCHDOG_ERROR);does not use the right parameters. If you want to specify an severity, you have to include the (in this case empty) array for use with t(). If you don't you will get an bad record in the database. It is not the problem of drupal core to prevent module developers from using core apis incorrectly.The other issue is that the bad record created by misusing watchdog breaks the dblog gui. It does not prevent future messages from being log. Because the proposed solution works in the theme layer, it will only work if the site is not using a custom theme_dblog_message. Once they do, it will probably be broken again.
There might be a solution by moving the unserialize call into the preprocess function, which can then account for bad data coming from the watchdog table, but this would not be backportable to d7 because it would break implementations of theme_dblog_message which rely on that parameter being serialzed.
Right now the solution is to fix bad calls to watchdog. If you need to have the proposed solution on your site, you should be able to get the same effect by implementing theme_dblog_message in your theme and use the logic in the attached patch.
Comment #12
pillarsdotnet commentedThis violates the "Never hide coding errors" culture of Drupal. Perhaps the main
watchdog()function could use some sanity-checking, like:Or even:
Comment #13
pillarsdotnet commentedSorry; crosspost.
My position is that:
Calling watchdog with invalid parameters should trigger an immediate error rather than silently making the error log unviewable.
It should be possible to view the error log even if one or more records contain bad data.
Comment #14
pfournier commentedI agree with pillarsdotnet.
Maybe, but it should at least use its own functions -- in this case, t() -- in a robust manner. The fact is that theme_dblog_message() cannot rely on receiving correct data from the DB. So it should at least check the data.
One can break so much things by reimplementing theme functions... I do not think this is a valid argument.
Sure the watchdog call needs to be fixed. However, even if I fix it now, I am stuck with an inaccessible log. I cant even clear it. Think of the users with no programming/SQL knowledge.
Comment #15
pillarsdotnet commentedHere is a tests-only patch. If at least one person agrees that this is the correct approach, I will attempt to write code that makes the test pass.
Comment #16
pillarsdotnet commentedMight as well let the testbot verify that it fails.
Comment #18
lars toomre commentedThis is one of those nice to have, but not need to have issues.
The primary fix to this issue is to call watchdog correctly (which I may be doing incorrectly since I frequently use NULL as the third parameter).
However, if bad values are written to the table (since there is no type checking on input), it should not result in the report page being inaccessible. The error log is one of the first places people turn when there is a problem. It sure would help if gave some clue about what the issue might be, especially for those just starting out on the steeep Drupal learning curve.
As a result, I am all for improvements and potential type checking in how the watchdog data might be used or summarized. +1 @pillarsdotnet.
Comment #19
adharris commentedI'm still not quite convinced that the proper course of action is to make watchdog throw an exception. It seems like it's venturing down the path of "it's the responsibility of the API to make sure it's used correctly." If it is important that we get an exception to prevent bad data into the watchdog table, should
Throw an exception as well?
I do, however, agree that the dblog should not be made unaccessible because of bad code. But since we can never catch all the ways bad data can be inserted into {watchdog}, the only solution which will prevent that is to fix it at display time (this making the proposed changes to watchdog a separate issue; one that is worth discussing). But is the proper way to do this by doing sanity checking in the theme layer?
Comment #20
pillarsdotnet commentedIt would certainly make it easier to troubleshoot the root cause of the problem, which is a bad call to watchdog. In general, the Drupal core philosophy of handling bad data from external code sources is to fail immediately and spectacularly, to provide both motivation and instruction in correcting the external coding error.
No, it's venturing down the path of "It's the responsibility of the API to report failure as soon as possible." Remember that the existing code also generates an exception, but only after an indeterminate amount of time has elapsed.
Exactly. The insert doesn't even have to come from Drupal, so there's no point trying to catch it at insert time, unless you're going to rely on non-portable database constraints.
I disagree. The proper thing is sanity checking before calling functions that assume a certain class of data, especially when failure would render debugging of the root cause more difficult.
But my point is:
Does this look like a valid test? If so, I'll code a solution that makes the test pass. If not, there's no point in trying.
Comment #21
adharris commentedIt looks like the functionality in the test is right, but the first part seems to be more a test against watchdog and not dblog. It probably belongs in a different test file; maybe bootstrap.test? Might even make sense to file the change for watchdog as another issue.
Comment #22
pillarsdotnet commentedOkay, here's my first attempt at making the tests pass. Let's see what the testbot says.
Comment #24
pillarsdotnet commentedCorrected.
Comment #26
pillarsdotnet commentedGrrr...
Comment #28
pillarsdotnet commentedMove sanity-check to its own function.
Comment #30
pillarsdotnet commentedAnother try...
Comment #32
pillarsdotnet commentedHow can the retrieved
NOT NULLfield value not be set?Comment #34
pillarsdotnet commentedOkay, maybe something is calling watchdog before
common.incis loaded?Comment #36
pillarsdotnet commentedOr maybe the database row object should be cloned before being modified?
Comment #38
pillarsdotnet commentedOkay, I give up. Going to test locally until I work out those bugs.
Comment #39
pillarsdotnet commentedOkay, this passes locally, although the
core/includes/common.incfragment may only be necessary because I'm running nginx instead of Apache.Comment #40
lars toomre commentedThe function does not actually return a sanitized object. Also surprised that dblog_overview() does not use the sanitized dblog object as I would expect based on the function name.
Comment #41
pillarsdotnet commentedUnnecessary hunks removed. The common.inc fragment was definitely a workaround for an nginx bug.
Comment #42
pillarsdotnet commented@Lars Toomre: Sorry; forgot to update header when I changed the function back.
Comment #43
pillarsdotnet commentedJust noticed those "11 passes" (WTF?)
Maybe fixing?
Comment #44
lars toomre commentedI forget that PHP 5.3+ passes as a default objects by reference. Does it make sense to modify the code to make it an explicit call by reference? This would result in the following and make clear how the sanitized result is returned.
Comment #45
pillarsdotnet commentedHere's the interdiff between #39 and #43:UPDATED: See #1502906: Bot #699 is passing everything in core with 11 assertions
(interdiff removed for brevity)
Comment #46
pillarsdotnet commentedInteresting that this sanity check caught an otherwise unnoticed bug. The
dblog_top()function wasn't bothering to select theseverityfield before passing data totheme('dblog_message'...).It would be quite natural for a theme implementation to assume that a dblog event object has a
severityfield and to theme the message display accordingly.Comment #47
pillarsdotnet commented@#44, No, passing an object by reference is an error. But I'll update the function header to note that it modifies the object in-place.
Also renamed
dblog_sanity_check()todblog_sanitize_row().Comment #48
lars toomre commentedMy understanding is that the docblock needs to start with an active verb (ie 'Sanitizes'). I would also change the subsequent explanation to be complete sentences, such as "This function ensures that the ..."
Comment #49
pillarsdotnet commentedCorrected.
Comment #50
avorio commentedHi folks,
I've just made the incorrect call to watchdog's function and now my logs are unaccessible.
How do I recover from that? Should I just truncate the watchdog table?
I'm glad you've also identified this issue.
a.
Comment #51
pfournier commentedYes, you can truncate the watchdog table.
If the table contains precious information, you can patch dblog using the proposed patch (#2 works for me), or reimplement theme_dblog_message().
Comment #52
chx commentedYou only make this mistake in development and then you can truncate and fix your code. It doesn't worth adding another N lines to core IMNSHO.
Comment #53
fuerst commentedIf you want Drupal not to stop at Recoverable Errors you may define your own error handler to overwrite Drupal's error handler function (see
_drupal_error_handler_real()).Place something like this in your
settings.php, preferably not at your production site:Comment #54
drupalshrek commentedThere are 3 reasons why I think this should be fixed, in decreasing order of importance:
1) It is important that Drupal core does not allow contributed modules to accidentally destroy core functionality. Let me give an example: let's say contributed module X accidentally includes an incorrectly coded watchdog() call. Imagine that hundreds of users (99% of whom have no SQL knowledge) install this version of the module along with other automatic upgrades. Most of them sooner or later have this wrongly coded call to watchdog() get called. This breaks completely the Report log. They are not programmers so they can never again check their Report log!! It was not Drupal core that caused the problem, but core should be a little more robust than that.
2) This is a huge pain for even normal developers. I hit this error because I've obviously made somewhere a mistaken call to watchdog(). It has now trashed my ability to easily view my production report log, which is extremely unfriendly. Sure, it was my fault for no doubt calling at some stage the watchdog() function with a wrong parameter, but to make the report log completely inaccessible is really a completely unacceptable error handling.
3) Much of the work to fix this problem has already been done by developers such as pillarsdotnet so I think adding a few extra lines of code to core is well worth the effort.
Comment #55
drupalshrek commentedIf you have some idea of which error messages are causing the problem you may get away with deleting only some of the watchdog messages, e.g.
Comment #56
marcingy commentedSee #1279680: watchdog() does not type its array arguments the solution was to add type hinting. The point is not that the work is done but the code is pointless apis should be called with appropriate parmeters and in a sensible way.
Comment #57
ianthomas_ukDuplicate of #1279680: watchdog() does not type its array arguments - discussion is still ongoing over there about exactly if / how this should be fixed.