Mercurial > public > mercurial-scm > hg-stable
diff mercurial/bundle2.py @ 23067:420a051616ce stable
bundle2: transmit exception during part generation
If an exception is raised during a bundle2 part payload generation it is now
recorded in the bundle. If such exception occurs, we capture it, transmit an
abort exception through the bundle, cleanly close the current part payload and
raise it again. This allow to generate valid bundle even in case of exception so
that the consumer does not wait forever for a dead producer. This also allow to
raise the exception during unbundling at the exact point it happened during
bundling make debugging easier.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Wed, 15 Oct 2014 03:52:20 -0700 |
parents | ad144882318d |
children | e53f6b72a0e4 |
line wrap: on
line diff
--- a/mercurial/bundle2.py Tue Oct 14 10:47:47 2014 -0700 +++ b/mercurial/bundle2.py Wed Oct 15 03:52:20 2014 -0700 @@ -145,6 +145,7 @@ preserve. """ +import sys import util import struct import urllib @@ -673,9 +674,22 @@ yield _pack(_fpartheadersize, len(headerchunk)) yield headerchunk ## payload - for chunk in self._payloadchunks(): - yield _pack(_fpayloadsize, len(chunk)) - yield chunk + try: + for chunk in self._payloadchunks(): + yield _pack(_fpayloadsize, len(chunk)) + yield chunk + except Exception, exc: + # backup exception data for later + exc_info = sys.exc_info() + msg = 'unexpected error: %s' % exc + interpart = bundlepart('b2x:error:abort', [('message', msg)]) + interpart.id = 0 + yield _pack(_fpayloadsize, -1) + for chunk in interpart.getchunks(): + yield chunk + # abort current part payload + yield _pack(_fpayloadsize, 0) + raise exc_info[0], exc_info[1], exc_info[2] # end of payload yield _pack(_fpayloadsize, 0) self._generated = True