Branko Cibej wrote:
> Maybe. Like I said, I'll have to remember what I was smoking^Wthinking
> when I wrote that code. I'm sure there was a good reason that all access
> wasn't through that function.
>
>> The cleanup code is complicated and I'm still working on understanding it.
>
> You don't say. I *wrote* it and still I have trouble understanding it. :(
Michael Zhang wrote this test case that reproduces the core dump we've been
seeing in our server. I tested it on my Mac OS X box and it fails there also.
$ svnadmin create --fs-type bdb /tmp/repos
$ gcc -Wall -o svntest -g -I/opt/local/include/apr-1
-I/opt/local/include/subversion-1 svntest.c -L/opt/local/lib -lsvn_repos-1
-lsvn_subr-1 -lapr-1
$ ./svntest /tmp/repos
The code needs to switch to more APR functions to make it in our test suite, but
it shows the issues.
#include <apr.h>
#include <svn_pools.h>
#include <svn_repos.h>
#include <pthread.h>
#define NUMTHREADS 2
apr_pool_t *gpool = NULL;
apr_pool_t *secondPool = NULL;
struct cond
{
pthread_mutex_t dataMutex;
pthread_cond_t dataPresentCondition;
pthread_cond_t cond2;
};
char *repos_path;
struct cond gcond = { PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER,
PTHREAD_COND_INITIALIZER
};
void *worker(void *arg)
{
int id = *(int *)arg;
int rc = 0;
svn_repos_t *repos;
apr_pool_t *pool = NULL;
if (id == 0)
{
pthread_mutex_lock(&gcond.dataMutex);
while (!secondPool)
{
pthread_cond_wait(&gcond.dataPresentCondition, &gcond.dataMutex);
}
pool = svn_pool_create(gpool);
svn_repos_open(&repos, repos_path, pool);
svn_pool_destroy(secondPool);
secondPool = NULL;
pthread_mutex_unlock(&gcond.dataMutex);
pthread_cond_signal(&gcond.cond2);
// This sleep make dbd reference count > 1 for a period time.
// Or else if dbd reference count = 0, the new svn_repos_open
// will call create_env again, which will hide the bug.
sleep(2);
}
else
{
// This sleep make thread 0 execute first to reach conditional wait status.
sleep(1);
pool = svn_pool_create(gpool);
svn_error_t *svn_err__temp = svn_repos_open(&repos, repos_path, pool);
if (svn_err__temp)
{
printf("There are some errors happened when trying to open repos.\n");
return NULL;
}
secondPool = pool;
rc = pthread_cond_signal(&gcond.dataPresentCondition);
pthread_mutex_lock(&gcond.dataMutex);
pthread_cond_wait(&gcond.cond2, &gcond.dataMutex);
pool = svn_pool_create(gpool);
svn_repos_open(&repos, repos_path, pool);
svn_pool_destroy(pool);
pthread_mutex_unlock(&gcond.dataMutex);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUMTHREADS];
pthread_attr_t attr;
int i;
int param[NUMTHREADS];
if (argc != 2)
{
fprintf(stderr, "usage: %s repos_path\n", argv[0]);
return 1;
}
repos_path = argv[1];
apr_initialize();
gpool = svn_pool_create(NULL);
pthread_attr_init(&attr);
for (i = 0; i < NUMTHREADS; ++i)
{
param[i] = i;
pthread_create(&threads[i], &attr, worker, param + i);
}
for (i = 0; i < NUMTHREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=980426
Received on 2008-12-08 22:58:06 CET