It's been a long time since I made the vague claim "serf breaks
the Python binding"; today I finally decided to try to narrow it
down. I have a tiny little C program that demonstrates the problem:
0 svn% ./serfbug svn://svn/r 84
fetched 118171
# neon
0 svn% ./serfbug https://svn/r 84
fetched 118171
# serf
0 svn% ./serfbug https://svn/r 84
subversion/libsvn_ra_serf/util.c:551: (apr_err=20014)
foo: Error running context: Internal error
*** glibc detected *** double free or corruption (!prev):
0x08098f68 ***
zsh: abort (core dumped) ./serfbug https://svn/r 84
This happens with both 1.5.x and trunk, fresh as of 5 minutes ago
(r31106). The error (but not the double free) goes away if you
pass revision instead of SVN_INVALID_REVNUM.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
/* for svn initialization */
#include <apr_errno.h>
#include <apr_general.h>
#include <apr_strings.h>
#include <svn_auth.h>
#include <svn_cmdline.h>
#include <svn_config.h>
#include <svn_dso.h>
#include <svn_nls.h>
#include <svn_pools.h>
/* for svn_ra_get_dir2 */
#include <apr_hash.h>
#include <svn_error.h>
#include <svn_io.h>
#include <svn_path.h>
#include <svn_ra.h>
static svn_error_t *
open_tmp_file(apr_file_t **fp, void *baton, apr_pool_t *pool)
{
const char *base_fn, *base_path, *fn;
SVN_ERR(svn_io_temp_dir(&base_fn, pool));
base_path = svn_path_join(base_fn, "foo", pool);
return svn_io_open_unique_file2(fp, &fn, base_path, ".tmp",
svn_io_file_del_on_close, pool);
}
#define ERR(expr) \
do { \
svn_error_t *err = (expr); \
if (err) { \
fprintf(stderr, "%s:%ld: (apr_err=%d)\nfoo: %s\n", \
err->file, err->line, err->apr_err, \
err->message); \
return 1; \
} \
} while (0)
int
main(int argc, char *argv[])
{
apr_pool_t *pool;
apr_hash_t *cfg_hash;
long revision;
svn_ra_callbacks2_t *callbacks;
if (argc < 3 || (argv[1] && argv[1][0] == '-')) {
fputs("usage: foo URL REVISION\n", stderr);
if (argv[1] && argv[1][0] == '-') {
return 0;
}
return 2;
}
errno = 0;
revision = strtol(argv[2], NULL, 10);
if (errno != 0) {
fprintf(stderr, "foo: strtol(%s): ", argv[2]);
perror("");
return 3;
}
/* Initialize svn. */
{
apr_status_t apr_status;
char buf[1024];
if ((apr_status = apr_initialize()) != APR_SUCCESS) {
apr_strerror(apr_status, buf, sizeof(buf) - 1);
fprintf(stderr, "foo: cannot initialize APR: %s\n", buf);
return 1;
}
svn_dso_initialize();
if (atexit(apr_terminate) != 0) {
fputs("atexit registration failed\n", stderr);
return 1;
}
pool = svn_pool_create(NULL);
svn_utf_initialize(pool);
ERR(svn_nls_init());
ERR(svn_config_get_config(&cfg_hash, NULL, pool));
ERR(svn_ra_initialize(pool));
ERR(svn_ra_create_callbacks(&callbacks, pool));
callbacks->open_tmp_file = open_tmp_file;
ERR(svn_cmdline_setup_auth_baton(&(callbacks->auth_baton),
TRUE, /* non_interactive */
NULL, /* username */
NULL, /* password */
NULL, /* config_dir */
FALSE, /* no_auth_cache */
apr_hash_get(cfg_hash,
SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING),
NULL, /* cancel_func */
NULL, /* cancel_baton */
pool));
}
/* Try something simple enough. */
{
svn_ra_session_t *ra;
apr_hash_t *dirents;
svn_revnum_t fetched_rev;
apr_hash_t *props;
ERR(svn_ra_open2(&ra, argv[1], callbacks, NULL, cfg_hash, pool));
ERR(svn_ra_get_dir2(ra, &dirents, &fetched_rev, &props,
"", /* path */
SVN_INVALID_REVNUM, /* revision */
0, /* dirent_fields */
pool));
printf("fetched %ld\n", fetched_rev);
}
return 0;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-05-09 03:06:42 CEST