aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/error.py
blob: fb76ecc7bb8221950c7c60d903a5a0b7496365d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# Sync content of this file with devtools/ya/core/error/__init__.py

TEMPORARY_ERROR_MESSAGES = [
    'Connection reset by peer',
    'Connection timed out',
    'Function not implemented',
    'I/O operation on closed file',
    'Internal Server Error',
    'Network connection closed unexpectedly',
    'Network is unreachable',
    'No route to host',
    'No space left on device',
    'Not enough space',
    'Temporary failure in name resolution',
    'The read operation timed out',
    'timeout: timed out',
    'no response given after',  # sandbox.common.rest.Client.TimeoutExceeded
]


# Node exit codes
class ExitCodes(object):
    GENERIC_ERROR = 1
    # 2 is reserved not to be confused with bash's exit code
    # For more info see https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
    _ = 2
    UNHANDLED_EXCEPTION = 3
    CONFIGURE_ERROR = 8
    NO_TESTS_COLLECTED = 9
    TEST_FAILED = 10
    INFRASTRUCTURE_ERROR = 12
    NOT_RETRIABLE_ERROR = 13
    YT_STORE_FETCH_ERROR = 14


def merge_exit_codes(exit_codes):
    return max(e if e >= 0 else 1 for e in exit_codes) if exit_codes else 0


def is_temporary_error(exc):
    import logging

    logger = logging.getLogger(__name__)

    if getattr(exc, 'temporary', False):
        logger.debug("Exception has temporary attribute: %s", exc)
        return True

    import errno

    err = getattr(exc, 'errno', None)

    if err == errno.ECONNREFUSED or err == errno.ENETUNREACH:
        logger.debug("Exception has errno attribute: %s (errno=%s)", exc, err)
        return True

    import socket

    if isinstance(exc, socket.timeout) or isinstance(getattr(exc, 'reason', None), socket.timeout):
        logger.debug("Socket timeout exception: %s", exc)
        return True

    if isinstance(exc, socket.gaierror):
        logger.debug("Getaddrinfo exception: %s", exc)
        return True

    try:
        import urllib2
        import httplib
    except ImportError:
        import urllib.request as urllib2
        import http.client as httplib

    if isinstance(exc, urllib2.HTTPError) and exc.code in (429,):
        logger.debug("urllib2.HTTPError: %s", exc)
        return True

    if isinstance(exc, httplib.IncompleteRead):
        logger.debug("IncompleteRead exception: %s", exc)
        return True

    exc_str = str(exc)

    for message in TEMPORARY_ERROR_MESSAGES:
        if message in exc_str:
            logger.debug("Found temporary error pattern (%s): %s", message, exc_str)
            return True

    return False