diff -r c153f440682f -r 313a940d49a3 mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py Tue Jul 03 12:22:37 2018 -0400 +++ b/mercurial/utils/procutil.py Wed Jun 27 10:47:14 2018 -0400 @@ -415,3 +415,36 @@ finally: if prevhandler is not None: signal.signal(signal.SIGCHLD, prevhandler) + +@contextlib.contextmanager +def uninterruptable(warn): + """Inhibit SIGINT handling on a region of code. + + Note that if this is called in a non-main thread, it turns into a no-op. + + Args: + warn: A callable which takes no arguments, and returns True if the + previous signal handling should be restored. + """ + + oldsiginthandler = [signal.getsignal(signal.SIGINT)] + shouldbail = [] + + def disabledsiginthandler(*args): + if warn(): + signal.signal(signal.SIGINT, oldsiginthandler[0]) + del oldsiginthandler[0] + shouldbail.append(True) + + try: + try: + signal.signal(signal.SIGINT, disabledsiginthandler) + except ValueError: + # wrong thread, oh well, we tried + del oldsiginthandler[0] + yield + finally: + if oldsiginthandler: + signal.signal(signal.SIGINT, oldsiginthandler[0]) + if shouldbail: + raise KeyboardInterrupt