You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Daniel Shahaf <d....@daniel.shahaf.name> on 2015/08/01 01:45:50 UTC

False positive "out of date" (SVN_ERR_FS_CONFLICT) with httpv1 and ra_serf

The bug described below is a race condition in the httpv1 protocol.
Since it doesn't affect httpv2, and mainly affects httpv1 in
high-concurrency situations (which would probably use httpv2 rather than
httpv1), I'm not sure we have any practical need to fix it.  However,
I'll document it here for posterity.

---

This was found by Philip's pre-release test runs.

Concurrent httpv1 commits sometimes trigger an SVN_ERR_FS_CONFLICT error
although they should merge() correctly.  The cause appears to be a race
condition in the httpv1 client code.

In subversion/libsvn_ra_serf/commit.c:open_root(), if the HEAD revision changes
between the MKACTIVITY request (line 1348) and the subsequent PROPFIND
/!svn/vcc/default request (svn_ra_serf__discover_vcc(), line 1354) will return
a VCC different from the txn's base revision, which leads dav_svn__checkout()
to fail the request at:

                  return dav_svn__new_error_svn
                    (resource->pool, HTTP_CONFLICT, SVN_ERR_FS_CONFLICT, 0,
                     "version resource newer than txn (restart the commit)");

This only affects servers configured with "SVNAdvertiseV2Protocol off", but is
reproducible with trunk:

[The patch triggers the race by forcing a specific linearization of two
 concurrent commit operations]
% svn patch mergeinfo_race-stall-MKACTIVITY.diff
% touch /tmp/svn.choose
% make -s svn
% APACHE_MPM=event USE_HTTPV1=yes ./davautocheck.sh svnadmin mergeinfo_race
W: subversion/svn/commit-cmd.c:185,
W: subversion/libsvn_client/commit.c:992,
W: subversion/libsvn_client/commit.c:156: (apr_err=SVN_ERR_WC_NOT_UP_TO_DATE)
W: svn: E155011: Commit failed (details follow):
W: subversion/libsvn_client/commit.c:904,
W: subversion/libsvn_client/commit_util.c:1884,
W: subversion/libsvn_delta/path_driver.c:264,
W: subversion/libsvn_client/commit_util.c:1834,
W: subversion/libsvn_client/commit_util.c:94: (apr_err=SVN_ERR_WC_NOT_UP_TO_DATE)
W: svn: E155011: Directory '/home/daniel/src/svn/t1/subversion/tests/cmdline/svn-test-work/working_copies/svnadmin_tests-30.2/d2' is out of date
W: subversion/libsvn_ra_serf/commit.c:1582,
W: subversion/libsvn_ra_serf/commit.c:406,
W: subversion/libsvn_ra_serf/commit.c:344,
W: subversion/libsvn_ra_serf/commit.c:284,
W: subversion/libsvn_ra_serf/util.c:988,
W: subversion/libsvn_ra_serf/util.c:937,
W: subversion/libsvn_ra_serf/util.c:902,
W: subversion/libsvn_ra_serf/multistatus.c:560: (apr_err=SVN_ERR_FS_CONFLICT)
W: svn: E160024: version resource newer than txn (restart the commit)

Note that retry_checkout_node() warns about — and tries to work around
— a similar race condition.

Cheers,

Daniel

P.S. Sorry about the unix-specific code in the patch; I tried the APR variant
(apr_proc_mutex_lock) first, but it didn't effect mutual exclusion, so rather
than figure out the bug in my code I just resorted to a straight flock().