From 1a7c9aa88448b9ffb121bbb0135d4ba70d8d9f00 Mon Sep 17 00:00:00 2001 From: Alexander Kozlovsky Date: Wed, 2 Aug 2023 14:48:39 +0200 Subject: [PATCH] CoreExceptionHandler should ignore all occurrences of ConnectionResetError --- .../components/reporter/exception_handler.py | 17 +++++++---- .../reporter/tests/test_exception_handler.py | 28 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/tribler/core/components/reporter/exception_handler.py b/src/tribler/core/components/reporter/exception_handler.py index e65824f8e5c..1b4d4a0be44 100644 --- a/src/tribler/core/components/reporter/exception_handler.py +++ b/src/tribler/core/components/reporter/exception_handler.py @@ -5,7 +5,7 @@ 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 @@ -13,20 +13,24 @@ 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.*' } @@ -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 diff --git a/src/tribler/core/components/reporter/tests/test_exception_handler.py b/src/tribler/core/components/reporter/tests/test_exception_handler.py index 0f936535520..41bf79779b7 100644 --- a/src/tribler/core/components/reporter/tests/test_exception_handler.py +++ b/src/tribler/core/components/reporter/tests/test_exception_handler.py @@ -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