Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -398,11 +398,14 @@ #ifndef SQLITE_OMIT_WAL int i; for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ - int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); + int nEntry; + sqlite3BtreeEnter(pBt); + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); } } } Index: test/threadtest4.c ================================================================== --- test/threadtest4.c +++ test/threadtest4.c @@ -14,17 +14,21 @@ ** from multiple threads in shared-cache mode. ** ** This test program runs on unix-like systems only. It uses pthreads. ** To compile: ** -** gcc -o tt4 -I. threadtest4.c sqlite3.c -ldl -lpthread +** gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread ** ** To run: ** -** ./tt4 10 +** ./a.out 10 +** +** The argument is the number of threads. There are also options, such +** as -wal and -multithread and -serialized. ** -** The argument is the number of threads. +** Consider also compiling with clang instead of gcc and adding the +** -fsanitize=thread option. */ #include "sqlite3.h" #include #include #include @@ -38,10 +42,11 @@ ** thread. */ typedef struct WorkerInfo WorkerInfo; struct WorkerInfo { int tid; /* Thread ID */ + int nWorker; /* Total number of workers */ unsigned wkrFlags; /* Flags */ sqlite3 *mainDb; /* Database connection of the main thread */ sqlite3 *db; /* Database connection of this thread */ int nErr; /* Number of errors seen by this thread */ int nTest; /* Number of tests run by this thread */ @@ -282,11 +287,11 @@ int i; int rc; sqlite3_stmt *pStmt; printf("worker %d startup\n", p->tid); fflush(stdout); - for(iOuter=1; iOuter<=4; iOuter++){ + for(iOuter=1; iOuter<=p->nWorker; iOuter++){ worker_open_connection(p, iOuter); for(i=0; i<4; i++){ worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter)%3 + 1); worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter+1)%3 + 1); worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter+2)%3 + 1); @@ -300,10 +305,21 @@ }else if( sqlite3_column_int(pStmt, 0)!=400 ){ worker_error(p, "Wrong result: %d", sqlite3_column_int(pStmt,0)); } if( p->nErr ) break; sqlite3_finalize(pStmt); + + if( ((iOuter+p->tid)%3)==0 ){ + sqlite3_db_release_memory(p->db); + p->nTest++; + } + + if( iOuter==p->tid ){ + pthread_mutex_lock(p->pWrMutex); + run_sql(p, "VACUUM"); + pthread_mutex_unlock(p->pWrMutex); + } worker_delete_all_content(p, (p->tid+iOuter)%2); worker_close_connection(p); p->db = 0; } @@ -360,10 +376,12 @@ "usage: %s ?OPTIONS? N\n" "N is the number of threads and must be at least 2.\n" "Options:\n" " --serialized\n" " --multithread\n" + " --wal\n" + " --trace\n" ,argv[0] ); exit(1); } if( !sqlite3_threadsafe() ){ @@ -404,10 +422,11 @@ run_sql(p, "CREATE INDEX test3.t3xy ON t3(x,y)"); aInfo = safe_malloc( sizeof(*aInfo)*nWorker ); memset(aInfo, 0, sizeof(*aInfo)*nWorker); for(i=0; i