diff --git a/mercurial/worker.py b/mercurial/worker.py index 4338f87dbf6fddb38c3ae08d91bf518525fae0b7_bWVyY3VyaWFsL3dvcmtlci5weQ==..86cd09bc13ba66386ad5f8fc0279168b282e5fd5_bWVyY3VyaWFsL3dvcmtlci5weQ== 100644 --- a/mercurial/worker.py +++ b/mercurial/worker.py @@ -15,6 +15,7 @@ from .i18n import _ from . import ( error, + scmutil, util, ) @@ -132,7 +133,8 @@ if pid == 0: signal.signal(signal.SIGINT, oldhandler) signal.signal(signal.SIGCHLD, oldchldhandler) - try: + + def workerfunc(): os.close(rfd) for i, item in func(*(staticargs + (pargs,))): os.write(wfd, '%d %s\n' % (i, item)) @@ -136,6 +138,11 @@ os.close(rfd) for i, item in func(*(staticargs + (pargs,))): os.write(wfd, '%d %s\n' % (i, item)) - os._exit(0) + + # make sure we use os._exit in all code paths. otherwise the worker + # may do some clean-ups which could cause surprises like deadlock. + # see sshpeer.cleanup for example. + try: + scmutil.callcatch(ui, workerfunc) except KeyboardInterrupt: os._exit(255) @@ -140,7 +147,12 @@ except KeyboardInterrupt: os._exit(255) - # other exceptions are allowed to propagate, we rely - # on lock.py's pid checks to avoid release callbacks + except: # never return, therefore no re-raises + try: + ui.traceback() + finally: + os._exit(255) + else: + os._exit(0) pids.add(pid) os.close(wfd) fp = os.fdopen(rfd, 'rb', 0)