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