xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/unittest/signals.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Workerimport signal
2*cda5da8dSAndroid Build Coastguard Workerimport weakref
3*cda5da8dSAndroid Build Coastguard Worker
4*cda5da8dSAndroid Build Coastguard Workerfrom functools import wraps
5*cda5da8dSAndroid Build Coastguard Worker
6*cda5da8dSAndroid Build Coastguard Worker__unittest = True
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard Workerclass _InterruptHandler(object):
10*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, default_handler):
11*cda5da8dSAndroid Build Coastguard Worker        self.called = False
12*cda5da8dSAndroid Build Coastguard Worker        self.original_handler = default_handler
13*cda5da8dSAndroid Build Coastguard Worker        if isinstance(default_handler, int):
14*cda5da8dSAndroid Build Coastguard Worker            if default_handler == signal.SIG_DFL:
15*cda5da8dSAndroid Build Coastguard Worker                # Pretend it's signal.default_int_handler instead.
16*cda5da8dSAndroid Build Coastguard Worker                default_handler = signal.default_int_handler
17*cda5da8dSAndroid Build Coastguard Worker            elif default_handler == signal.SIG_IGN:
18*cda5da8dSAndroid Build Coastguard Worker                # Not quite the same thing as SIG_IGN, but the closest we
19*cda5da8dSAndroid Build Coastguard Worker                # can make it: do nothing.
20*cda5da8dSAndroid Build Coastguard Worker                def default_handler(unused_signum, unused_frame):
21*cda5da8dSAndroid Build Coastguard Worker                    pass
22*cda5da8dSAndroid Build Coastguard Worker            else:
23*cda5da8dSAndroid Build Coastguard Worker                raise TypeError("expected SIGINT signal handler to be "
24*cda5da8dSAndroid Build Coastguard Worker                                "signal.SIG_IGN, signal.SIG_DFL, or a "
25*cda5da8dSAndroid Build Coastguard Worker                                "callable object")
26*cda5da8dSAndroid Build Coastguard Worker        self.default_handler = default_handler
27*cda5da8dSAndroid Build Coastguard Worker
28*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, signum, frame):
29*cda5da8dSAndroid Build Coastguard Worker        installed_handler = signal.getsignal(signal.SIGINT)
30*cda5da8dSAndroid Build Coastguard Worker        if installed_handler is not self:
31*cda5da8dSAndroid Build Coastguard Worker            # if we aren't the installed handler, then delegate immediately
32*cda5da8dSAndroid Build Coastguard Worker            # to the default handler
33*cda5da8dSAndroid Build Coastguard Worker            self.default_handler(signum, frame)
34*cda5da8dSAndroid Build Coastguard Worker
35*cda5da8dSAndroid Build Coastguard Worker        if self.called:
36*cda5da8dSAndroid Build Coastguard Worker            self.default_handler(signum, frame)
37*cda5da8dSAndroid Build Coastguard Worker        self.called = True
38*cda5da8dSAndroid Build Coastguard Worker        for result in _results.keys():
39*cda5da8dSAndroid Build Coastguard Worker            result.stop()
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker_results = weakref.WeakKeyDictionary()
42*cda5da8dSAndroid Build Coastguard Workerdef registerResult(result):
43*cda5da8dSAndroid Build Coastguard Worker    _results[result] = 1
44*cda5da8dSAndroid Build Coastguard Worker
45*cda5da8dSAndroid Build Coastguard Workerdef removeResult(result):
46*cda5da8dSAndroid Build Coastguard Worker    return bool(_results.pop(result, None))
47*cda5da8dSAndroid Build Coastguard Worker
48*cda5da8dSAndroid Build Coastguard Worker_interrupt_handler = None
49*cda5da8dSAndroid Build Coastguard Workerdef installHandler():
50*cda5da8dSAndroid Build Coastguard Worker    global _interrupt_handler
51*cda5da8dSAndroid Build Coastguard Worker    if _interrupt_handler is None:
52*cda5da8dSAndroid Build Coastguard Worker        default_handler = signal.getsignal(signal.SIGINT)
53*cda5da8dSAndroid Build Coastguard Worker        _interrupt_handler = _InterruptHandler(default_handler)
54*cda5da8dSAndroid Build Coastguard Worker        signal.signal(signal.SIGINT, _interrupt_handler)
55*cda5da8dSAndroid Build Coastguard Worker
56*cda5da8dSAndroid Build Coastguard Worker
57*cda5da8dSAndroid Build Coastguard Workerdef removeHandler(method=None):
58*cda5da8dSAndroid Build Coastguard Worker    if method is not None:
59*cda5da8dSAndroid Build Coastguard Worker        @wraps(method)
60*cda5da8dSAndroid Build Coastguard Worker        def inner(*args, **kwargs):
61*cda5da8dSAndroid Build Coastguard Worker            initial = signal.getsignal(signal.SIGINT)
62*cda5da8dSAndroid Build Coastguard Worker            removeHandler()
63*cda5da8dSAndroid Build Coastguard Worker            try:
64*cda5da8dSAndroid Build Coastguard Worker                return method(*args, **kwargs)
65*cda5da8dSAndroid Build Coastguard Worker            finally:
66*cda5da8dSAndroid Build Coastguard Worker                signal.signal(signal.SIGINT, initial)
67*cda5da8dSAndroid Build Coastguard Worker        return inner
68*cda5da8dSAndroid Build Coastguard Worker
69*cda5da8dSAndroid Build Coastguard Worker    global _interrupt_handler
70*cda5da8dSAndroid Build Coastguard Worker    if _interrupt_handler is not None:
71*cda5da8dSAndroid Build Coastguard Worker        signal.signal(signal.SIGINT, _interrupt_handler.original_handler)
72