Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/ui.py @ 33668:cde4cfeb6e3e stable
ui: restore behavior to ignore some I/O errors (issue5658)
e9646ff34d55 and 1bfb9a63b98e refactored ui methods to no longer
silently swallow some IOError instances. This is arguably the
correct thing to do. However, it had the unfortunate side-effect
of causing StdioError to bubble up to sensitive code like
transaction aborts, leading to an uncaught exceptions and failures
to e.g. roll back a transaction. This could occur when a remote
HTTP or SSH client connection dropped. The new behavior is
resulting in semi-frequent "abandonded transaction" errors on
multiple high-volume repositories at Mozilla.
This commit effectively reverts e9646ff34d55 and 1bfb9a63b98e to
restore the old behavior.
I agree with the principle that I/O errors shouldn't be ignored.
That makes this change... unfortunate. However, our hands are tied
for what to do on stable. I think the proper solution is for the
ui's behavior to be configurable (possibly via a context manager).
During critical sections like transaction rollback and abort, it
should be possible to suppress errors. But this feature would not
be appropriate on stable.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 15 Aug 2017 13:04:31 -0700 |
parents | c2c6a0f7408b |
children | 0e4bed5c5c38 af20468eb0a4 |
comparison
equal
deleted
inserted
replaced
33667:2debf1e3cfa4 | 33668:cde4cfeb6e3e |
---|---|
902 # stderr may be buffered under win32 when redirected to files, | 902 # stderr may be buffered under win32 when redirected to files, |
903 # including stdout. | 903 # including stdout. |
904 if not getattr(self.ferr, 'closed', False): | 904 if not getattr(self.ferr, 'closed', False): |
905 self.ferr.flush() | 905 self.ferr.flush() |
906 except IOError as inst: | 906 except IOError as inst: |
907 raise error.StdioError(inst) | 907 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): |
908 raise error.StdioError(inst) | |
908 | 909 |
909 def flush(self): | 910 def flush(self): |
910 # opencode timeblockedsection because this is a critical path | 911 # opencode timeblockedsection because this is a critical path |
911 starttime = util.timer() | 912 starttime = util.timer() |
912 try: | 913 try: |
913 try: | 914 try: |
914 self.fout.flush() | 915 self.fout.flush() |
915 except IOError as err: | 916 except IOError as err: |
916 raise error.StdioError(err) | 917 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): |
918 raise error.StdioError(err) | |
917 finally: | 919 finally: |
918 try: | 920 try: |
919 self.ferr.flush() | 921 self.ferr.flush() |
920 except IOError as err: | 922 except IOError as err: |
921 raise error.StdioError(err) | 923 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): |
924 raise error.StdioError(err) | |
922 finally: | 925 finally: |
923 self._blockedtimes['stdio_blocked'] += \ | 926 self._blockedtimes['stdio_blocked'] += \ |
924 (util.timer() - starttime) * 1000 | 927 (util.timer() - starttime) * 1000 |
925 | 928 |
926 def _isatty(self, fh): | 929 def _isatty(self, fh): |