[PATCH 1 of 2 STABLE] tests: demonstrate that I/O error can lead to orphaned transaction (issue5658)

Gregory Szorc gregory.szorc at gmail.com
Mon Aug 14 20:52:57 UTC 2017


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1502741560 25200
#      Mon Aug 14 13:12:40 2017 -0700
# Branch stable
# Node ID 0a33f202bca4ee7ea126e7638bb74b5d58775858
# Parent  7686cbb0ba4138c56d038d8d82ccc052bf9b60d7
tests: demonstrate that I/O error can lead to orphaned transaction (issue5658)

ui._write(), ui._write_err(), and ui.flush() all trap IOError and
re-raise as error.StdioError. If a caller doesn't catch StdioError
when writing to stdio, it could bubble all the way to dispatch.

This commit adds tests for I/O failures around transaction rollback.

It shows that an uncaught StdioError for printing "transaction abort!" can
lead to an abandonded transaction.

StdioError for hook output, however, it properly dealt with.

And errors during "rollback completed" can also result in wonkiness.

diff --git a/tests/test-rollback.t b/tests/test-rollback.t
--- a/tests/test-rollback.t
+++ b/tests/test-rollback.t
@@ -210,3 +210,99 @@ rollback disabled by config
   abort: rollback is disabled because it is unsafe
   (see `hg help -v rollback` for information)
   [255]
+
+  $ cd ..
+
+I/O errors on stdio are handled properly (issue5658)
+
+  $ cat > badui.py << EOF
+  > import errno
+  > from mercurial.i18n import _
+  > from mercurial import (
+  >     error,
+  >     ui as uimod,
+  > )
+  > 
+  > def txnabort(ui, repo, **kwargs):
+  >     ui.warn('warn during abort\n')
+  > 
+  > def uisetup(ui):
+  >     class badui(ui.__class__):
+  >         def write_err(self, *args, **opts):
+  >             errors = set(self.configlist('ui', 'ioerrors', []))
+  >             txnabort = _('transaction abort!\n') in args
+  >             txnaborthook = 'warn during abort\n' in args
+  >             txnrollback = _('rollback completed\n') in args
+  > 
+  >             if txnabort and 'txnabort' in errors:
+  >                 raise error.StdioError(IOError(errno.EPIPE, 'simulated epipe'))
+  >             if txnaborthook and 'txnaborthook' in errors:
+  >                 raise error.StdioError(IOError(errno.EBADF, 'simulated ebadf'))
+  >             if txnrollback and 'txnrollback' in errors:
+  >                 raise error.StdioError(IOError(errno.EIO, 'simulated eio'))
+  > 
+  >             return super(badui, self).write_err(*args, **opts)
+  >     ui.__class__ = badui
+  > 
+  > def reposetup(ui, repo):
+  >     ui.setconfig('hooks', 'txnabort.badui', txnabort, 'badui')
+  > EOF
+
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > badui = $TESTTMP/badui.py
+  > EOF
+
+An I/O error writing "transaction abort" should still result in rollback
+
+  $ hg init ioerror-abort
+  $ cd ioerror-abort
+
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=txnabort --config hooks.pretxncommit=false commit -m 'error during abort message'
+  *: DeprecationWarning: use lock.release instead of del lock (glob)
+    return -1
+  [255]
+
+  $ hg commit -m 'commit 1'
+  abort: abandoned transaction found!
+  (run 'hg recover' to clean up transaction)
+  [255]
+
+  $ cd ..
+
+An I/O error during transaction abort callback should still result in rollback
+
+  $ hg init ioerror-abortcallback
+  $ cd ioerror-abortcallback
+
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=txnaborthook --config hooks.pretxncommit=false commit -m 'error during abort'
+  transaction abort!
+  error: txnabort.badui hook raised an exception: [Errno 9] simulated ebadf
+  (run with --traceback for stack trace)
+  rollback completed
+  abort: pretxncommit hook exited with status 1
+  [255]
+
+An I/O error writing "rollback completed" should still result in rollback
+
+  $ hg --config ui.ioerrors=txnrollback --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]
+
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  1 files, 1 changesets, 1 total revisions


More information about the Mercurial-devel mailing list