Mercurial > hg
changeset 33755: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 | 2debf1e3cfa4 |
children | 0e15d5ae52cf |
files | mercurial/ui.py tests/test-rollback.t |
diffstat | 2 files changed, 20 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/ui.py Mon Aug 14 13:12:40 2017 -0700 +++ b/mercurial/ui.py Tue Aug 15 13:04:31 2017 -0700 @@ -904,7 +904,8 @@ if not getattr(self.ferr, 'closed', False): self.ferr.flush() except IOError as inst: - raise error.StdioError(inst) + if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): + raise error.StdioError(inst) def flush(self): # opencode timeblockedsection because this is a critical path @@ -913,12 +914,14 @@ try: self.fout.flush() except IOError as err: - raise error.StdioError(err) + if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): + raise error.StdioError(err) finally: try: self.ferr.flush() except IOError as err: - raise error.StdioError(err) + if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): + raise error.StdioError(err) finally: self._blockedtimes['stdio_blocked'] += \ (util.timer() - starttime) * 1000
--- a/tests/test-rollback.t Mon Aug 14 13:12:40 2017 -0700 +++ b/tests/test-rollback.t Tue Aug 15 13:04:31 2017 -0700 @@ -302,16 +302,12 @@ warn during txnclose $ echo 1 > foo $ hg --config ui.ioerrors=pretxncommit commit -m 'error during pretxncommit' - error: pretxncommit.badui hook raised an exception: [Errno *] simulated epipe (glob) - transaction abort! - warn during abort - rollback completed - [255] + warn during pretxnclose + warn during txnclose $ hg commit -m 'commit 1' - warn during pretxncommit - warn during pretxnclose - warn during txnclose + nothing changed + [1] $ cd .. @@ -328,17 +324,11 @@ $ echo 1 > foo $ hg --config ui.ioerrors=pretxnclose commit -m 'error during pretxnclose' warn during pretxncommit - error: pretxnclose.badui hook raised an exception: [Errno *] simulated eio (glob) - transaction abort! - warn during abort - rollback completed - abort: simulated eio - [255] + warn during txnclose $ hg commit -m 'commit 1' - warn during pretxncommit - warn during pretxnclose - warn during txnclose + nothing changed + [1] $ cd .. @@ -356,8 +346,6 @@ $ hg --config ui.ioerrors=txnclose commit -m 'error during txnclose' warn during pretxncommit warn during pretxnclose - error: txnclose.badui hook raised an exception: [Errno *] simulated badf (glob) - (run with --traceback for stack trace) $ hg commit -m 'commit 1' nothing changed @@ -378,15 +366,15 @@ $ echo 1 > foo $ hg --config ui.ioerrors=msgabort --config hooks.pretxncommit=false commit -m 'error during abort message' - abort: simulated ebadf - *: DeprecationWarning: use lock.release instead of del lock (glob) - return -1 + warn during abort + rollback completed + abort: pretxncommit hook exited with status 1 [255] $ hg commit -m 'commit 1' - abort: abandoned transaction found! - (run 'hg recover' to clean up transaction) - [255] + warn during pretxncommit + warn during pretxnclose + warn during txnclose $ cd .. @@ -404,8 +392,6 @@ $ echo 1 > foo $ hg --config ui.ioerrors=txnabort --config hooks.pretxncommit=false commit -m 'error during abort' transaction abort! - error: txnabort.badui hook raised an exception: [Errno *] simulated epipe (glob) - (run with --traceback for stack trace) rollback completed abort: pretxncommit hook exited with status 1 [255] @@ -433,7 +419,6 @@ $ hg --config ui.ioerrors=msgrollback --config hooks.pretxncommit=false commit -m 'error during rollback message' transaction abort! warn during abort - rollback failed - please run hg recover abort: pretxncommit hook exited with status 1 [255] @@ -461,25 +446,12 @@ $ echo 1 > foo $ hg --config ui.ioerrors=pretxncommit,pretxnclose,txnclose,txnabort,msgabort,msgrollback commit -m 'multiple errors' - error: pretxncommit.badui hook raised an exception: [Errno *] simulated epipe (glob) - abort: simulated ebadf - *: DeprecationWarning: use lock.release instead of del lock (glob) - return -1 - [255] $ hg verify - abandoned transaction found - run hg recover checking changesets checking manifests - manifest@?: rev 1 points to nonexistent changeset 1 - manifest@?: 94e0ee43dbfe not in changesets crosschecking files in changesets and manifests checking files - foo@?: rev 1 points to nonexistent changeset 1 - (expected 0) - 1 files, 1 changesets, 2 total revisions - 1 warnings encountered! - 3 integrity errors encountered! - [1] + 1 files, 2 changesets, 2 total revisions $ cd ..