Mercurial > hg
comparison mercurial/dispatch.py @ 28520:84cc72c5771e
dispatch: catch KeyboardInterrupt more broadly
Because _runcatch() can run long operations in its exception handler,
it wasn't enough to catch KeyboardInterrupt at the same level. For
example, "hg unknown" will load all extension modules, so we could
easily make it crashed by Ctrl-C.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 27 Dec 2015 13:38:46 +0900 |
parents | 491eabd0df79 |
children | 293adbaa14a7 |
comparison
equal
deleted
inserted
replaced
28519:518a5030acba | 28520:84cc72c5771e |
---|---|
118 msg = ' '.join(' ' in a and repr(a) or a for a in req.args) | 118 msg = ' '.join(' ' in a and repr(a) or a for a in req.args) |
119 starttime = time.time() | 119 starttime = time.time() |
120 ret = None | 120 ret = None |
121 try: | 121 try: |
122 ret = _runcatch(req) | 122 ret = _runcatch(req) |
123 return ret | 123 except KeyboardInterrupt: |
124 try: | |
125 req.ui.warn(_("interrupted!\n")) | |
126 except IOError as inst: | |
127 if inst.errno != errno.EPIPE: | |
128 raise | |
129 ret = -1 | |
124 finally: | 130 finally: |
125 duration = time.time() - starttime | 131 duration = time.time() - starttime |
126 req.ui.log("commandfinish", "%s exited %s after %0.2f seconds\n", | 132 req.ui.log("commandfinish", "%s exited %s after %0.2f seconds\n", |
127 msg, ret or 0, duration) | 133 msg, ret or 0, duration) |
134 return ret | |
128 | 135 |
129 def _runcatch(req): | 136 def _runcatch(req): |
130 def catchterm(*args): | 137 def catchterm(*args): |
131 raise error.SignalInterrupt | 138 raise error.SignalInterrupt |
132 | 139 |
311 if getattr(inst, "filename", None) is not None: | 318 if getattr(inst, "filename", None) is not None: |
312 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename)) | 319 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename)) |
313 else: | 320 else: |
314 ui.warn(_("abort: %s\n") % inst.strerror) | 321 ui.warn(_("abort: %s\n") % inst.strerror) |
315 except KeyboardInterrupt: | 322 except KeyboardInterrupt: |
316 try: | 323 raise |
317 ui.warn(_("interrupted!\n")) | |
318 except IOError as inst: | |
319 if inst.errno != errno.EPIPE: | |
320 raise | |
321 except MemoryError: | 324 except MemoryError: |
322 ui.warn(_("abort: out of memory\n")) | 325 ui.warn(_("abort: out of memory\n")) |
323 except SystemExit as inst: | 326 except SystemExit as inst: |
324 # Commands shouldn't sys.exit directly, but give a return code. | 327 # Commands shouldn't sys.exit directly, but give a return code. |
325 # Just in case catch this and and pass exit code to caller. | 328 # Just in case catch this and and pass exit code to caller. |