[PATCH 2 of 2] bundle2: transmit exception during part generation
Augie Fackler
raf at durin42.com
Wed Oct 22 00:41:31 CDT 2014
On Tue, Oct 21, 2014 at 01:08:46PM -0700, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at fb.com>
> # Date 1413370340 25200
> # Wed Oct 15 03:52:20 2014 -0700
> # Branch stable
> # Node ID bd35fb4708eda7d548a34ef6ff504505cf0e85cb
> # Parent 1c1b98ea77615d601d8234f70728da9a21692c93
> 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.
>
> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
> --- a/mercurial/bundle2.py
> +++ b/mercurial/bundle2.py
> @@ -143,10 +143,11 @@ process is aborted, the full bundle is s
> channel usable. But none of the part read from an abort are processed. In the
> future, dropping the stream may become an option for channel we do not care to
> preserve.
> """
>
> +import sys
> import util
> import struct
> import urllib
> import string
> import obsolete
> @@ -671,13 +672,26 @@ class bundlepart(object):
> ## finalize header
> headerchunk = ''.join(header)
> 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:
> + # backup exception data for later
> + exc_info = sys.exc_info()
> + msg = 'unexpected error: %s' % exc
exc isn't defined here - did you mean exc_info, or did you want to
catch the exception as 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
>
> def _payloadchunks(self):
> diff --git a/tests/test-bundle2-format.t b/tests/test-bundle2-format.t
> --- a/tests/test-bundle2-format.t
> +++ b/tests/test-bundle2-format.t
> @@ -775,28 +775,25 @@ with reply
> added 0 changesets with 0 changes to 3 files
> \x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
>
> Check handling of exception during generation.
> ----------------------------------------------
> -(is currently not right)
>
> $ hg bundle2 --genraise > ../genfailed.hg2
> abort: Someone set up us the bomb!
> [255]
>
> Should still be a valid bundle
> -(is currently not right)
>
> $ cat ../genfailed.hg2
> HG2Y\x00\x00\x00\x00\x00\x00\x00\x11 (esc)
> - b2x:output\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
> + b2x:output\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00L\x0fb2x:error:abort\x00\x00\x00\x00\x01\x00\x07-messageunexpected error: Someone set us up the bomb!\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
>
> And its handling on the other size raise a clean exception
> -(is currently not right)
>
> $ cat ../genfailed.hg2 | hg unbundle2
> 0 unread bytes
> - abort: stream ended unexpectedly (got 0 bytes, expected 4)
> + abort: unexpected error: Someone set us up the bomb!
> [255]
>
>
> $ cd ..
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list