mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Fix thread related problems in test modules test_async.c and test_journal.c. (CVS 6399)
FossilOrigin-Name: 45df27a22d283871ed1de334fe3b74b0121d57a6
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Back\sout\scheck-in\s(6380).\s\sReplace\sit\swith\sa\sproper\sfix\sto\sthe\nxFullPathname\smethod\sin\sthe\sasync\sVFS.\s(CVS\s6398)
|
C Fix\sthread\srelated\sproblems\sin\stest\smodules\stest_async.c\sand\stest_journal.c.\s(CVS\s6399)
|
||||||
D 2009-03-28T15:04:24
|
D 2009-03-28T17:21:52
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -173,7 +173,7 @@ F src/test6.c 1a0a7a1f179469044b065b4a88aab9faee114101
|
|||||||
F src/test7.c b94e68c2236de76889d82b8d7d8e00ad6a4d80b1
|
F src/test7.c b94e68c2236de76889d82b8d7d8e00ad6a4d80b1
|
||||||
F src/test8.c 3637439424d0d21ff2dcf9b015c30fcc1e7bcb24
|
F src/test8.c 3637439424d0d21ff2dcf9b015c30fcc1e7bcb24
|
||||||
F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
|
F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
|
||||||
F src/test_async.c 9d75004dfee306f823cc26525cfef718c2e024d2
|
F src/test_async.c fd2344c394ad27e76274aa60b74a1ad5ff27533e
|
||||||
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
|
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
|
||||||
F src/test_backup.c 79ac8daa03f0b3d360ff1eb56b23c7df0c14ecd1
|
F src/test_backup.c 79ac8daa03f0b3d360ff1eb56b23c7df0c14ecd1
|
||||||
F src/test_btree.c d7b8716544611c323860370ee364e897c861f1b0
|
F src/test_btree.c d7b8716544611c323860370ee364e897c861f1b0
|
||||||
@@ -181,7 +181,7 @@ F src/test_config.c a05378089b6773ba36b85727dedf9ec0a16424ce
|
|||||||
F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4
|
F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4
|
||||||
F src/test_func.c dd7bcaafb4e149702b506ede125ef6a4d4f6c471
|
F src/test_func.c dd7bcaafb4e149702b506ede125ef6a4d4f6c471
|
||||||
F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
|
F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
|
||||||
F src/test_journal.c 1d3fd9e79d8be1d99cdffa0b774805b2c962c782
|
F src/test_journal.c 1e7baebc212b2c79f03f2c647cfd0b4f3678bf4c
|
||||||
F src/test_loadext.c 97dc8800e46a46ed002c2968572656f37e9c0dd9
|
F src/test_loadext.c 97dc8800e46a46ed002c2968572656f37e9c0dd9
|
||||||
F src/test_malloc.c d23050c7631ec9ee0369c7ca905e6c9233968e11
|
F src/test_malloc.c d23050c7631ec9ee0369c7ca905e6c9233968e11
|
||||||
F src/test_md5.c 032ae2bb6f81da350d2404e81fa8d560c8268026
|
F src/test_md5.c 032ae2bb6f81da350d2404e81fa8d560c8268026
|
||||||
@@ -710,7 +710,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
|||||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
P 9278f7b1e1f2d0d4c2f8829ca801a769e512c2a6
|
P 767a7f7b55456df404a7f8966a0c48318ddac120
|
||||||
R 121873619f687e25693398fc7592b8b5
|
R 4d38ca30ee6ed6fda0e3455931bed136
|
||||||
U drh
|
U danielk1977
|
||||||
Z 4d0af7748a59ba8b5aec187f6438633a
|
Z e66cb9677f3d8d7ca66409e784f05095
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
767a7f7b55456df404a7f8966a0c48318ddac120
|
45df27a22d283871ed1de334fe3b74b0121d57a6
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
** $Id: test_async.c,v 1.54 2009/03/28 15:04:24 drh Exp $
|
** $Id: test_async.c,v 1.55 2009/03/28 17:21:52 danielk1977 Exp $
|
||||||
**
|
**
|
||||||
** This file contains an example implementation of an asynchronous IO
|
** This file contains an example implementation of an asynchronous IO
|
||||||
** backend for SQLite.
|
** backend for SQLite.
|
||||||
@@ -483,7 +483,6 @@ static int async_mutex_lock(pthread_mutex_t *pMutex){
|
|||||||
assert(&(aHolder[2])==&asyncdebug.writerMutexHolder);
|
assert(&(aHolder[2])==&asyncdebug.writerMutexHolder);
|
||||||
|
|
||||||
assert( pthread_self()!=0 );
|
assert( pthread_self()!=0 );
|
||||||
|
|
||||||
for(iIdx=0; iIdx<3; iIdx++){
|
for(iIdx=0; iIdx<3; iIdx++){
|
||||||
if( pMutex==&aMutex[iIdx] ) break;
|
if( pMutex==&aMutex[iIdx] ) break;
|
||||||
|
|
||||||
@@ -610,7 +609,9 @@ static void assert_mutex_is_held(pthread_mutex_t *pMutex){
|
|||||||
*/
|
*/
|
||||||
static void addAsyncWrite(AsyncWrite *pWrite){
|
static void addAsyncWrite(AsyncWrite *pWrite){
|
||||||
/* We must hold the queue mutex in order to modify the queue pointers */
|
/* We must hold the queue mutex in order to modify the queue pointers */
|
||||||
|
if( pWrite->op!=ASYNC_UNLOCK ){
|
||||||
pthread_mutex_lock(&async.queueMutex);
|
pthread_mutex_lock(&async.queueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the record to the end of the write-op queue */
|
/* Add the record to the end of the write-op queue */
|
||||||
assert( !pWrite->pNext );
|
assert( !pWrite->pNext );
|
||||||
@@ -629,7 +630,9 @@ static void addAsyncWrite(AsyncWrite *pWrite){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Drop the queue mutex */
|
/* Drop the queue mutex */
|
||||||
|
if( pWrite->op!=ASYNC_UNLOCK ){
|
||||||
pthread_mutex_unlock(&async.queueMutex);
|
pthread_mutex_unlock(&async.queueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
/* The writer thread might have been idle because there was nothing
|
/* The writer thread might have been idle because there was nothing
|
||||||
** on the write-op queue for it to do. So wake it up. */
|
** on the write-op queue for it to do. So wake it up. */
|
||||||
@@ -956,10 +959,12 @@ static int asyncUnlock(sqlite3_file *pFile, int eLock){
|
|||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
if( p->zName ){
|
if( p->zName ){
|
||||||
AsyncFileLock *pLock = &p->lock;
|
AsyncFileLock *pLock = &p->lock;
|
||||||
|
pthread_mutex_lock(&async.queueMutex);
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
pLock->eLock = MIN(pLock->eLock, eLock);
|
pLock->eLock = MIN(pLock->eLock, eLock);
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
|
||||||
rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
|
rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
|
||||||
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
|
pthread_mutex_unlock(&async.queueMutex);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -1526,8 +1531,46 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ASYNC_UNLOCK: {
|
case ASYNC_UNLOCK: {
|
||||||
|
AsyncWrite *pIter;
|
||||||
AsyncFileData *pData = p->pFileData;
|
AsyncFileData *pData = p->pFileData;
|
||||||
int eLock = p->nByte;
|
int eLock = p->nByte;
|
||||||
|
|
||||||
|
/* When a file is locked by SQLite using the async backend, it is
|
||||||
|
** locked within the 'real' file-system synchronously. When it is
|
||||||
|
** unlocked, an ASYNC_UNLOCK event is added to the write-queue to
|
||||||
|
** unlock the file asynchronously. The design of the async backend
|
||||||
|
** requires that the 'real' file-system file be locked from the
|
||||||
|
** time that SQLite first locks it (and probably reads from it)
|
||||||
|
** until all asynchronous write events that were scheduled before
|
||||||
|
** SQLite unlocked the file have been processed.
|
||||||
|
**
|
||||||
|
** This is more complex if SQLite locks and unlocks the file multiple
|
||||||
|
** times in quick succession. For example, if SQLite does:
|
||||||
|
**
|
||||||
|
** lock, write, unlock, lock, write, unlock
|
||||||
|
**
|
||||||
|
** Each "lock" operation locks the file immediately. Each "write"
|
||||||
|
** and "unlock" operation adds an event to the event queue. If the
|
||||||
|
** second "lock" operation is performed before the first "unlock"
|
||||||
|
** operation has been processed asynchronously, then the first
|
||||||
|
** "unlock" cannot be safely processed as is, since this would mean
|
||||||
|
** the file was unlocked when the second "write" operation is
|
||||||
|
** processed. To work around this, when processing an ASYNC_UNLOCK
|
||||||
|
** operation, SQLite:
|
||||||
|
**
|
||||||
|
** 1) Unlocks the file to the minimum of the argument passed to
|
||||||
|
** the xUnlock() call and the current lock from SQLite's point
|
||||||
|
** of view, and
|
||||||
|
**
|
||||||
|
** 2) Only unlocks the file at all if this event is the last
|
||||||
|
** ASYNC_UNLOCK event on this file in the write-queue.
|
||||||
|
*/
|
||||||
|
assert( holdingMutex==1 );
|
||||||
|
assert( async.pQueueFirst==p );
|
||||||
|
for(pIter=async.pQueueFirst->pNext; pIter; pIter=pIter->pNext){
|
||||||
|
if( pIter->pFileData==pData && pIter->op==ASYNC_UNLOCK ) break;
|
||||||
|
}
|
||||||
|
if( !pIter ){
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
pData->lock.eAsyncLock = MIN(
|
pData->lock.eAsyncLock = MIN(
|
||||||
pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
|
pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
|
||||||
@@ -1535,6 +1578,7 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
assert(pData->lock.eAsyncLock>=pData->lock.eLock);
|
assert(pData->lock.eAsyncLock>=pData->lock.eLock);
|
||||||
rc = getFileLock(pData->pLock);
|
rc = getFileLock(pData->pLock);
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
** correctly populates and syncs a journal file before writing to a
|
** correctly populates and syncs a journal file before writing to a
|
||||||
** corresponding database file.
|
** corresponding database file.
|
||||||
**
|
**
|
||||||
** $Id: test_journal.c,v 1.13 2009/03/26 11:49:11 danielk1977 Exp $
|
** $Id: test_journal.c,v 1.14 2009/03/28 17:21:52 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#if SQLITE_TEST /* This file is used for testing only */
|
#if SQLITE_TEST /* This file is used for testing only */
|
||||||
|
|
||||||
@@ -206,6 +206,17 @@ struct JtGlobal {
|
|||||||
};
|
};
|
||||||
static struct JtGlobal g = {0, 0};
|
static struct JtGlobal g = {0, 0};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Functions to obtain and relinquish a mutex to protect g.pList. The
|
||||||
|
** STATIC_PRNG mutex is reused, purely for the sake of convenience.
|
||||||
|
*/
|
||||||
|
static void enterJtMutex(void){
|
||||||
|
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
|
||||||
|
}
|
||||||
|
static void leaveJtMutex(void){
|
||||||
|
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
|
||||||
|
}
|
||||||
|
|
||||||
extern int sqlite3_io_error_pending;
|
extern int sqlite3_io_error_pending;
|
||||||
static void stop_ioerr_simulation(int *piSave){
|
static void stop_ioerr_simulation(int *piSave){
|
||||||
*piSave = sqlite3_io_error_pending;
|
*piSave = sqlite3_io_error_pending;
|
||||||
@@ -236,11 +247,12 @@ static int jtClose(sqlite3_file *pFile){
|
|||||||
jt_file *p = (jt_file *)pFile;
|
jt_file *p = (jt_file *)pFile;
|
||||||
|
|
||||||
closeTransaction(p);
|
closeTransaction(p);
|
||||||
|
enterJtMutex();
|
||||||
if( p->zName ){
|
if( p->zName ){
|
||||||
for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext);
|
for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext);
|
||||||
*pp = p->pNext;
|
*pp = p->pNext;
|
||||||
}
|
}
|
||||||
|
leaveJtMutex();
|
||||||
return sqlite3OsClose(p->pReal);
|
return sqlite3OsClose(p->pReal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +269,6 @@ static int jtRead(
|
|||||||
return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
|
return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Parameter zJournal is the name of a journal file that is currently
|
** Parameter zJournal is the name of a journal file that is currently
|
||||||
** open. This function locates and returns the handle opened on the
|
** open. This function locates and returns the handle opened on the
|
||||||
@@ -274,6 +285,7 @@ static int jtRead(
|
|||||||
**/
|
**/
|
||||||
static jt_file *locateDatabaseHandle(const char *zJournal){
|
static jt_file *locateDatabaseHandle(const char *zJournal){
|
||||||
jt_file *pMain = 0;
|
jt_file *pMain = 0;
|
||||||
|
enterJtMutex();
|
||||||
for(pMain=g.pList; pMain; pMain=pMain->pNext){
|
for(pMain=g.pList; pMain; pMain=pMain->pNext){
|
||||||
int nName = strlen(zJournal) - strlen("-journal");
|
int nName = strlen(zJournal) - strlen("-journal");
|
||||||
if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
|
if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
|
||||||
@@ -284,6 +296,7 @@ static jt_file *locateDatabaseHandle(const char *zJournal){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
leaveJtMutex();
|
||||||
return pMain;
|
return pMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,10 +682,12 @@ static int jtOpen(
|
|||||||
p->pNext = 0;
|
p->pNext = 0;
|
||||||
p->pWritable = 0;
|
p->pWritable = 0;
|
||||||
p->aCksum = 0;
|
p->aCksum = 0;
|
||||||
|
enterJtMutex();
|
||||||
if( zName ){
|
if( zName ){
|
||||||
p->pNext = g.pList;
|
p->pNext = g.pList;
|
||||||
g.pList = p;
|
g.pList = p;
|
||||||
}
|
}
|
||||||
|
leaveJtMutex();
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user