[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Assert in svn-1.7-alpha2 svn_client_merge3

From: Julian Foad <julian.foad_at_wandisco.com>
Date: Tue, 12 Jul 2011 15:02:56 +0100

On Mon, 2011-07-11 at 12:23 +0100, Julian Foad wrote:
> On Sat, 2011-07-09, Barry Scott wrote:
> > svn built with ./configure --prefix=/usr/local --enable-debug on
> > Fedora 15 x86_64.
>
> Hi Barry. This stack trace and info is useful, ...
>
> > Let me know if you want to run this yourself. I can provide a tarball
> > with the pysvn sources that trigger this and easy instructions to
> > reproduce.
>
> ... but Yes Please! That would be fantastic. If it's smaller than 100
> KB just attach it here on the list; if bigger, please email to me
> off-list (and I suspect Paul Burba would be interested too).
>
> In the meantime, this is what I can see so far ...
>
>
> > I'm testing 1.7-alpha2 against pysvn and I'm seeing an assert
> > when calling svn_client_merge3. This has all works against 1.6.
> >
> > Is this a bug in svn or pysvn calling svn?
> >
> >
> >
> >
> > Here is what was printed:
> >
> > Info: pysvn command: merge --revision 16:17
> > file:///home/barry/wc/svn/pysvn/Extension/Tests/testroot-01/root/repos/trunk/test /home/barry/wc/svn/pysvn/Extension/Tests/testroot-01/wc3/test-branch
> > subversion/libsvn_subr/mergeinfo.c:801: (apr_err=235000)
> > svn: E235000: In file 'subversion/libsvn_subr/mergeinfo.c' line 801:
> > assertion failed (IS_VALID_FORWARD_RANGE(first))
> > ./test-01-qqq.sh: line 16: 9958 Aborted (core dumped)
> > ${PYSVN} "$@"
> >
> >
> > And gdb output of the stack, the call site and the variables passed
> > into svn_client_merge3.
>
> (I've hand-edited the stack trace quoted here for readability, stripping
> out some memory addresses and other less interesting things.)
>
> > #3 svn_error__malfunction ... "IS_VALID_FORWARD_RANGE(first)"
>
> #define IS_VALID_FORWARD_RANGE(range) \
> (SVN_IS_VALID_REVNUM((range)->start) && ((range)->start < (range)->end))
>
> > #4 range_contains (first=0x19c32b8, ...)
> > at subversion/libsvn_subr/mergeinfo.c:801
>
> This is failing to validate an element of the 'rangelist1' input ...
>
> > #5 rangelist_intersect_or_remove (..., rangelist1=0x19c3290, ...)
> > at subversion/libsvn_subr/mergeinfo.c:959
> > #6 svn_rangelist_intersect (..., rangelist1=0x19c3290, ...)
> > at subversion/libsvn_subr/mergeinfo.c:1107
> > #7 adjust_deleted_subtree_ranges (child=0x19bf4e0, parent=0x194c1d8,
> > mergeinfo_path="/trunk/test/file-merge-1.txt", revision1=16,
> > revision2=17,
> > primary_url="file:///.../trunk/test/file-merge-1.txt", ...)
> > at subversion/libsvn_client/merge.c:2908
>
> ... which is a single-element rangelist created here by:
>
> /* Create a rangelist describing the range PRIMARY_URL_at_older_rev
> exists and find the intersection of that and
> CHILD->REMAINING_RANGES. */
> svn_rangelist__initialize(older_rev,
> revision_primary_url_deleted - 1,
> TRUE, scratch_pool);
>
> This makes range->start = older_rev which would be 16 (AFAICT from
> reading the code), and range->end = (rev...deleted - 1).
> 'rev...deleted' comes from:
>
> /* PRIMARY_URL_at_older_rev exists, so it was deleted at some
> revision prior to peg_rev, find that revision. */
> SVN_ERR(svn_ra_get_deleted_rev(ra_session,
> rel_source_path [=.../file-merge-1.txt],
> older_rev [=16], younger_rev [=17],
> &revision_primary_url_deleted,
> scratch_pool));
>
> and this whole code path is entered because file-merge-1.txt doesn't
> exist in r17, so it looks like that "-1" is the problem. Presumably
> 'rev...deleted' is being set to 17 and so an invalid range of (start=16,
> end=16) is being created. The 'end' of a rangelist is supposed be be
> exclusive not inclusive.

Correction: if it's a forward range, then it's the 'start' of a
rangelist that is supposed to be exclusive; the 'end' is inclusive.

In this case what's happening is simply that we're creating an empty
range (where start == end), but an empty range is considered invalid.

The simplest fix is probably just to set the intersection result to the
empty set, so I would expect the following patch to fix the problem.

[[[
@@ @@ adjust_deleted_subtree_ranges(svn_client...
     /* Create a rangelist describing the range PRIMARY_URL_at_older_rev
        exists and find the intersection of that and
        CHILD->REMAINING_RANGES. */
+ if (revision_primary_url_deleted - 1 > older_rev)
+ {
+ /* It was not deleted immediately after OLDER_REV, so
            it has some relevant changes. */
     exists_rangelist =
       svn_rangelist__initialize(older_rev,
                                 revision_primary_url_deleted - 1,
                                 TRUE, scratch_pool);
     SVN_ERR(svn_rangelist_intersect(&(child->remaining_ranges),
                                     exists_rangelist,
                                     child->remaining_ranges,
                                     FALSE, scratch_pool));
+ }
+ else
+ {
+ /* It was deleted immediately after the OLDER rev, so
+ it has no relevant changes. */
+ child->remaining_ranges = apr_array_make(scratch_pool, 0,
+ sizeof(svn_merge_range_t *));
+ }
]]]

> I'll have a go now at reproducing this problem without your test data,
> but it would be good to confirm it with your test data.

There are three existing tests that exercise this code path, which I
found by inserting a debug print statement here and running the test
suite:

  merge_authz_tests.py 2
    relpath='D/gamma', older_rev=1, younger_rev=6, rev...deleted=5

  merge_tests.py 83
    relpath='D/H/psi', older_rev=1, younger_rev=12, rev...deleted=7

  merge_tests.py 94
    relpath='psi', older_rev=1, younger_rev=9, rev...deleted=8

I'm still trying to create a new test specifically for this problem.

- Julian
Received on 2011-07-12 16:03:38 CEST

This is an archived mail posted to the Subversion Dev mailing list.