Index: subversion/libsvn_subr/error.c =================================================================== --- subversion/libsvn_subr/error.c (revision 1052167) +++ subversion/libsvn_subr/error.c (working copy) @@ -349,39 +349,47 @@ svn_error_purge_tracing(svn_error_t *err) { #ifdef SVN_ERR__TRACING - svn_error_t *tmp_err = err; svn_error_t *new_err = NULL, *new_err_leaf = NULL; if (! err) return SVN_NO_ERROR; - while (tmp_err) + do { /* Skip over any trace-only links. */ - while (tmp_err && is_tracing_link(tmp_err)) - tmp_err = tmp_err->child; + while (err && is_tracing_link(err)) + err = err->child; - /* Add a new link to the new chain (creating the chain if necessary). */ - if (! new_err) + if (err) { - new_err = tmp_err; - new_err_leaf = new_err; + /* Copy the current error except for its child error pointer + into the new error. Share any message and source + filename strings from the error. */ + svn_error_t *tmp_err = apr_palloc(err->pool, sizeof(*tmp_err)); + *tmp_err = *err; + tmp_err->child = NULL; + + /* Add a new link to the new chain (creating the chain if + necessary). */ + if (! new_err) + { + new_err = tmp_err; + new_err_leaf = tmp_err; + } + else + { + new_err_leaf->child = tmp_err; + new_err_leaf = tmp_err; + } + + /* Advance to the next link in the original chain. */ + err = err->child; } - else - { - new_err_leaf->child = tmp_err; - new_err_leaf = new_err_leaf->child; - } + } while (err); - /* Advance to the next link in the original chain. */ - tmp_err = tmp_err->child; - } - /* If we get here, there had better be a real link in this error chain. */ SVN_ERR_ASSERT(new_err_leaf); - /* Tie off the chain, and return its head. */ - new_err_leaf->child = NULL; return new_err; #else /* SVN_ERR__TRACING */ return err; Index: subversion/mod_dav_svn/deadprops.c =================================================================== --- subversion/mod_dav_svn/deadprops.c (revision 1052167) +++ subversion/mod_dav_svn/deadprops.c (working copy) @@ -222,18 +222,22 @@ resource->pool); /* Prepare any hook failure message to get sent over the wire */ - serr = svn_error_purge_tracing(serr); - if (serr && serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE) - serr->message = apr_xml_quote_string(serr->pool, serr->message, 1); - - /* mod_dav doesn't handle the returned error very well, it - generates its own generic error that will be returned to - the client. Cache the detailed error here so that it can - be returned a second time when the rollback mechanism - triggers. */ if (serr) - resource->info->revprop_error = svn_error_dup(serr); + { + svn_error_t *purged_serr = svn_error_purge_tracing(serr); + if (purged_serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE) + purged_serr->message = apr_xml_quote_string + (purged_serr->pool, + purged_serr->message, 1); + /* mod_dav doesn't handle the returned error very well, it + generates its own generic error that will be returned to + the client. Cache the detailed error here so that it can + be returned a second time when the rollback mechanism + triggers. */ + resource->info->revprop_error = svn_error_dup(purged_serr); + } + /* Tell the logging subsystem about the revprop change. */ dav_svn__operational_log(resource->info, svn_log__change_rev_prop( Index: subversion/mod_dav_svn/version.c =================================================================== --- subversion/mod_dav_svn/version.c (revision 1052167) +++ subversion/mod_dav_svn/version.c (working copy) @@ -922,16 +922,16 @@ { if (serr) { - const char *post_commit_err; - apr_err = serr->apr_err; - post_commit_err = svn_repos__post_commit_error_str - (serr, resource->pool); - serr = SVN_NO_ERROR; - ap_log_perror(APLOG_MARK, APLOG_ERR, apr_err, resource->pool, + const char *post_commit_err = svn_repos__post_commit_error_str + (serr, resource->pool); + ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err, + resource->pool, "commit of r%ld succeeded, but an error occurred " "after the commit: '%s'", new_rev, post_commit_err); + svn_error_clear(serr); + serr = SVN_NO_ERROR; } } else @@ -1421,6 +1421,7 @@ ### client some other way than hijacking the post-commit ### error message.*/ post_commit_err = svn_repos__post_commit_error_str(serr, pool); + svn_error_clear(serr); serr = SVN_NO_ERROR; } } Index: subversion/mod_dav_svn/util.c =================================================================== --- subversion/mod_dav_svn/util.c (revision 1052167) +++ subversion/mod_dav_svn/util.c (working copy) @@ -111,7 +111,7 @@ /* Remove the trace-only error chain links. We need predictable protocol behavior regardless of whether or not we're in a debugging build. */ - serr = svn_error_purge_tracing(serr); + svn_error_t *purged_serr = svn_error_purge_tracing(serr); /* ### someday mod_dav_svn will send back 'rich' error tags, much finer grained than plain old svn_error_t's. But for now, all @@ -122,7 +122,7 @@ appropriate HTTP status code. If no more appropriate HTTP status code maps to the Subversion error code, use the one suggested status provided by the caller. */ - switch (serr->apr_err) + switch (purged_serr->apr_err) { case SVN_ERR_FS_NOT_FOUND: status = HTTP_NOT_FOUND; @@ -139,11 +139,12 @@ /* add other mappings here */ } - derr = build_error_chain(pool, serr, status); + derr = build_error_chain(pool, purged_serr, status); if (message != NULL - && serr->apr_err != SVN_ERR_REPOS_HOOK_FAILURE) + && purged_serr->apr_err != SVN_ERR_REPOS_HOOK_FAILURE) /* Don't hide hook failures; we might hide the error text */ - derr = dav_push_error(pool, status, serr->apr_err, message, derr); + derr = dav_push_error(pool, status, purged_serr->apr_err, + message, derr); /* Now, destroy the Subversion error. */ svn_error_clear(serr); Index: subversion/include/svn_error.h =================================================================== --- subversion/include/svn_error.h (revision 1052167) +++ subversion/include/svn_error.h (working copy) @@ -315,12 +315,19 @@ #endif /** - * Purge from @a err and its child chain any links associated with - * error tracing placeholders, and return the new top-level error - * chain item. @a err should be considered unusable after passing - * through this function, but should *not* be cleared (as the returned - * error shares memory with @a err). @a err can be #SVN_NO_ERROR. + * Returns an error chain that is based on @a err's error chain but + * does not include any error tracing placeholders. @a err is not + * modified, except for any allocations using its pool. * + * The returned error chain is allocated from @a err's pool and shares + * its message and source filename character arrays. The returned + * error chain should *not* be cleared because it is not a fully + * fledged error chain, only clearing @a err should be done to clear + * the returned error chain. If @a err is cleared, then the returned + * error chain is unusable. + * + * @a err can be #SVN_NO_ERROR. + * * @since New in 1.7. */ svn_error_t *svn_error_purge_tracing(svn_error_t *err); Index: subversion/include/private/svn_repos_private.h =================================================================== --- subversion/include/private/svn_repos_private.h (revision 1052167) +++ subversion/include/private/svn_repos_private.h (working copy) @@ -91,8 +91,7 @@ * the post-commit hook. Any error tracing placeholders in the error * chain are skipped over. * - * This function clears @a err and it should not be used after passing - * it to this function. + * This function does not modify @a err. * * ### This method should not be necessary, but there are a few * ### places, e.g. mod_dav_svn, where only a single error message Index: subversion/libsvn_repos/commit.c =================================================================== --- subversion/libsvn_repos/commit.c (revision 1052167) +++ subversion/libsvn_repos/commit.c (working copy) @@ -705,11 +705,6 @@ : _("(no error message)")); } - /* Because svn_error_purge_tracing() was used on the input error, - the purged error must either be cleared here or returned to the - caller. This function just clears it. */ - svn_error_clear(err); - return msg; } @@ -743,6 +738,7 @@ (to be reported back to the client, who will probably display it as a warning) and clear the error. */ post_commit_err = svn_repos__post_commit_error_str(err, pool); + svn_error_clear(err); err = SVN_NO_ERROR; } }