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

Re: Berkeley DB help needed [was Re: [PATCH] BDB error_info threading issue causing core dumps]

From: Blair Zajac <blair_at_orcaware.com>
Date: Fri, 05 Dec 2008 18:00:07 -0800

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

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