[3.0] Count the errors that are on the stack, not the errors that happened - #9606
[3.0] Count the errors that are on the stack, not the errors that happened#9606albertlast wants to merge 1 commit into
Conversation
The guard that stops error logging looping is a count of how deep the call is, and it was only cleared by reaching the end of the method. Returning early because logging is switched off skipped that, so the count kept climbing and the third error in a request died with a backtrace and 'loop detected' even though nothing had recursed. Balancing the count in a finally covers that return, and any error raised between the two, without depending on where the method ends up leaving. Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
|
in my opinion the bot change many code, dunno if we want this way? |
|
All it looks to be doing is wrapping a try statement around it so it can decrement it. If an error happens while logging an error, we are in a situation that won't recover. If we make it to the return, resetting the count is fine. |
|
Yeah, but the recursive error case isn't affected by this branch. When error logging is disabled, the three separate errors in one request (three undefined indexes) reportedly trip the loop detection. |
|
Thats because of this code: SMF/Sources/Services/ErrorHandlerService.php Lines 231 to 234 in 8d94f6d Its missing the reset of the error level as seen by the main exit SMF/Sources/Services/ErrorHandlerService.php Lines 350 to 354 in 8d94f6d Adding it there will fix the issue. |
|
Or move the logging disabled up. We can't catch a loop detection if we are not logging. |
Description
ErrorHandlerService::log()keeps a count so that an error raised while logging an error does not go round for ever. The count is incremented on the way in and was cleared by reaching the end of the method:That early return skips the reset. With error logging switched off the count therefore climbs on every call and never comes back down, so the third error in a request dies — with a
var_dump()of a backtrace and "loop detected" — even though nothing recursed and the three errors had nothing to do with each other.The count is now balanced in a
finally, which covers that return and also the case where something between the two throws. Nothing else changes: the threshold and the message are what they were, and on the path that already worked the count still goes from one back to zero.Most of the diff is the reindentation for the
try.git diff -wis nine lines.How it turned up
On the Windows job added in #9601. The runner has no
fileinfoextension,Utils::getMimeType()logsrequired_extension_missingwhen it is absent,Avatarcalls it for every gallery avatar, and the third one killed PHPUnit outright:The extension is dealt with separately in #9601. This is the other half: three unrelated errors should not be a loop.
It is not specific to tests or to Windows. Any forum with error logging turned off dies on the third logged error of a request, and shows a raw backtrace while doing it. The same shape is in 2.1's
log_error(), so it has been there a long while.Tests
tests/Unit/ErrorHandlerServiceTest.phplogs five errors with logging off and asserts each returns its message. With logging off the method returns before it touches the database, so this stays on the near side of the line.Against the unfixed code it does not merely fail, it reproduces the bug exactly:
Genuine recursion still ends in the same
die(), which cannot be asserted from inside the process that dies, so that path is unchanged and untested.One thing left alone deliberately: the
var_dump($backtrace)before thedie()writes paths straight to the response. It is worth removing, but it is a different argument from this one and I did not want to bundle it. Happy to follow up.Issues References (Fixes|Related|Closes)