Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CoreExceptionHandler should ignore all occurrences of ConnectionResetError #7566

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/tribler/core/components/reporter/exception_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,32 @@
from io import StringIO
from socket import gaierror
from traceback import print_exception
from typing import Callable, Optional
from typing import Callable, Dict, Optional, Set, Tuple, Type

from tribler.core.components.exceptions import ComponentStartupException
from tribler.core.components.reporter.reported_error import ReportedError
from tribler.core.sentry_reporter.sentry_reporter import SentryReporter
from tribler.core.utilities.process_manager import get_global_process_manager

# There are some errors that we are ignoring.
IGNORED_ERRORS_BY_CODE = {

IGNORED_ERRORS_BY_CLASS: Tuple[Type[Exception], ...] = (
ConnectionResetError, # Connection forcibly closed by the remote host.
gaierror, # all gaierror is ignored
)

IGNORED_ERRORS_BY_CODE: Set[Tuple[Type[Exception], int]] = {
(OSError, 113), # No route to host is non-critical since Tribler can still function when a request fails.
# Socket block: this sometimes occurs on Windows and is non-critical.
(BlockingIOError, 10035 if sys.platform == 'win32' else errno.EWOULDBLOCK),
(OSError, 51), # Could not send data: network is unreachable.
(ConnectionAbortedError, 10053), # An established connection was aborted by the software in your host machine.
(ConnectionResetError, 10054), # Connection forcibly closed by the remote host.
(OSError, 10022), # Failed to get address info.
(OSError, 16), # Socket error: Device or resource busy.
(OSError, 0)
}

IGNORED_ERRORS_BY_REGEX = {
gaierror: r'', # all gaierror is ignored
IGNORED_ERRORS_BY_REGEX: Dict[Type[Exception], str] = {
RuntimeError: r'.*invalid info-hash.*'
}

Expand Down Expand Up @@ -58,6 +62,9 @@ def _is_ignored(exception: Exception):
exception_class = exception.__class__
error_number = exception.errno if hasattr(exception, 'errno') else None

if isinstance(exception, IGNORED_ERRORS_BY_CLASS):
return True

if (exception_class, error_number) in IGNORED_ERRORS_BY_CODE:
return True

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,32 @@ def raise_error(error): # pylint: disable=inconsistent-return-statements
def test_is_ignored(exception_handler):
# test that CoreExceptionHandler ignores specific exceptions

# by type
assert exception_handler._is_ignored(OSError(113, 'Any'))
assert exception_handler._is_ignored(ConnectionResetError(10054, 'Any'))
# by exception type
assert exception_handler._is_ignored(gaierror())
assert exception_handler._is_ignored(ConnectionResetError())

# by class
assert exception_handler._is_ignored(gaierror('Any'))
# by exception type and error code
assert exception_handler._is_ignored(OSError(113, 'Arbitrary error message'))
assert exception_handler._is_ignored(OSError(0, 'Arbitrary error message'))

# by class and substring
assert exception_handler._is_ignored(RuntimeError('Message that contains invalid info-hash'))
# by exception type and regex
assert exception_handler._is_ignored(RuntimeError('A message with the following substring: invalid info-hash'))
assert not exception_handler._is_ignored(RuntimeError('Another message without a substring'))


def test_is_not_ignored(exception_handler):
# test that CoreExceptionHandler do not ignore exceptions out of
# IGNORED_ERRORS_BY_CODE and IGNORED_ERRORS_BY_SUBSTRING
assert not exception_handler._is_ignored(OSError(1, 'Any'))
assert not exception_handler._is_ignored(RuntimeError('Any'))
# IGNORED_ERRORS_BY_TYPE, IGNORED_ERRORS_BY_CODE and IGNORED_ERRORS_BY_SUBSTRING

# AttributeError is not in the IGNORED_ERRORS_BY_TYPE, IGNORED_ERRORS_BY_CODE or IGNORED_ERRORS_BY_SUBSTRING
assert not exception_handler._is_ignored(AttributeError())

# OSError with code 1 is not in the IGNORED_ERRORS_BY_CODE
assert not exception_handler._is_ignored(OSError(1, 'Arbitrary error message'))

# RuntimeError is in IGNORED_ERRORS_BY_REGEX, but the message does not contain "invalid info-hash" substring
assert not exception_handler._is_ignored(RuntimeError('Arbitrary error message'))


def test_create_exception_from(exception_handler):
# test that CoreExceptionHandler can create an Exception from a string
Expand Down
Loading