Skip to content

[3.0] Count the errors that are on the stack, not the errors that happened - #9606

Open
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/errorhandler-recursion
Open

[3.0] Count the errors that are on the stack, not the errors that happened#9606
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/errorhandler-recursion

Conversation

@albertlast

Copy link
Copy Markdown
Collaborator

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:

$error_call++;
...
if ($error_call > 2) {
    var_dump($backtrace);
    die('Error: loop detected. The database may have failed or crashed.');
}

// Check if error logging is actually on.
if (empty(Config::$modSettings['enableErrorLogging'])) {
    return $error_message;          // never reaches the reset below
}
...
// Reset error call
$error_call = 0;

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 -w is nine lines.

How it turned up

On the Windows job added in #9601. The runner has no fileinfo extension, Utils::getMimeType() logs required_extension_missing when it is absent, Avatar calls it for every gallery avatar, and the third one killed PHPUnit outright:

Error: loop detected. The database may have failed or crashed.
Fatal error: Premature end of PHP process when running
SMF\Tests\Unit\AvatarTest::testAGalleryAvatarInTheRootOfTheGalleryIsFoundToo

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.php logs 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:

Error: loop detected. The database may have failed or crashed.
Fatal error: Premature end of PHP process when running
SMF\Tests\Unit\ErrorHandlerServiceTest::testErrorsThatAreNotLoggedDoNotCountAsALoop

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 the die() 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)

  1. Related to [3.0][Testing] Run the unit tests on Windows as well as Linux #9601

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>
@albertlast

Copy link
Copy Markdown
Collaborator Author

in my opinion the bot change many code, dunno if we want this way?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant