diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py --- a/mercurial/commandserver.py +++ b/mercurial/commandserver.py @@ -355,7 +355,18 @@ ) try: - ret = self._dispatchcommand(req) & 255 + err = None + try: + status = self._dispatchcommand(req) + except error.StdioError as e: + status = -1 + err = e + + retval = dispatch.closestdio(req.ui, err) + if retval: + status = retval + + ret = status & 255 # If shutdown-on-interrupt is off, it's important to write the # result code *after* SIGINT handler removed. If the result code # were lost, the client wouldn't be able to continue processing. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -104,6 +104,35 @@ raise exc +def closestdio(ui, err): + status = None + # In all cases we try to flush stdio streams. + if util.safehasattr(ui, b'fout'): + assert ui is not None # help pytype + assert ui.fout is not None # help pytype + try: + ui.fout.flush() + except IOError as e: + err = e + status = -1 + + if util.safehasattr(ui, b'ferr'): + assert ui is not None # help pytype + assert ui.ferr is not None # help pytype + try: + if err is not None and err.errno != errno.EPIPE: + ui.ferr.write( + b'abort: %s\n' % encoding.strtolocal(err.strerror) + ) + ui.ferr.flush() + # There's not much we can do about an I/O error here. So (possibly) + # change the status code and move on. + except IOError: + status = -1 + + return status + + def run(): """run the command in sys.argv""" try: @@ -117,30 +146,9 @@ err = e status = -1 - # In all cases we try to flush stdio streams. - if util.safehasattr(req.ui, b'fout'): - assert req.ui is not None # help pytype - assert req.ui.fout is not None # help pytype - try: - req.ui.fout.flush() - except IOError as e: - err = e - status = -1 - - if util.safehasattr(req.ui, b'ferr'): - assert req.ui is not None # help pytype - assert req.ui.ferr is not None # help pytype - try: - if err is not None and err.errno != errno.EPIPE: - req.ui.ferr.write( - b'abort: %s\n' % encoding.strtolocal(err.strerror) - ) - req.ui.ferr.flush() - # There's not much we can do about an I/O error here. So (possibly) - # change the status code and move on. - except IOError: - status = -1 - + ret = closestdio(req.ui, err) + if ret: + status = ret _silencestdio() except KeyboardInterrupt: # Catch early/late KeyboardInterrupt as last ditch. Here nothing will