From: dan Date: Tue, 7 Dec 2010 16:39:25 +0000 (+0000) Subject: Fix a bug in the demo "superlock" code preventing locks from being released in some... X-Git-Tag: version-3.7.4~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c216eee7ce2211ffd363b3885b34f161f3bc237f;p=thirdparty%2Fsqlite.git Fix a bug in the demo "superlock" code preventing locks from being released in some circumstances. FossilOrigin-Name: 65c393793ff5fdb935d5acfe5bdc3bca052f7314 --- diff --git a/manifest b/manifest index 14f5ca8663..10f8555a8c 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Version\s3.7.4\srelease\scandidate\s3 -D 2010-12-07T14:59:22 +C Fix\sa\sbug\sin\sthe\sdemo\s"superlock"\scode\spreventing\slocks\sfrom\sbeing\sreleased\sin\ssome\scircumstances. +D 2010-12-07T16:39:26 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -220,7 +217,7 @@ F src/test_rtree.c 30c981837445a4e187ee850a49c4760d9642f7c3 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6 F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c -F src/test_superlock.c c0c0b1f73254a0c4ad5aca69e627fe32f571f7f9 +F src/test_superlock.c aa91c01e42c8e1eef663b74bd1b9a762306f06b5 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0 F src/test_vfs.c e10fcca756cafa89438311b31522ac1f95bf784b @@ -657,7 +654,7 @@ F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796 F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a -F test/superlock.test 070e7fd9ccf91755b6f8e03ede27995a73220672 +F test/superlock.test 8468e057d8a5531ff99e504e77fcc585a0291bf2 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 7262a8cbaa9965d429f1cbd2747edc185fa56516 @@ -897,14 +894,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P b0634d2f909fb192d20315e59fa31fcd8f316541 -R c899dedfcbfad993e519fd17027aa5c1 -U drh -Z e558719848264f114302cf252022d7ad ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFM/kvQoxKgR168RlERAihjAJ483qru/mKHGZtSh1P4zl69jepBKwCfe11S -MaOtcUGzrbyHLk/lC2rzkPk= -=bBvs ------END PGP SIGNATURE----- +P 11c74c0dae0e302f248ec4af6dc8a9376203b034 +R b4c637d07289308a3222d68447f4c6c3 +U dan +Z 63bd98324f51b062689452a6abdd2cdc diff --git a/manifest.uuid b/manifest.uuid index 281813f1d5..63640be6f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -11c74c0dae0e302f248ec4af6dc8a9376203b034 \ No newline at end of file +65c393793ff5fdb935d5acfe5bdc3bca052f7314 \ No newline at end of file diff --git a/src/test_superlock.c b/src/test_superlock.c index 8a49188658..464da55076 100644 --- a/src/test_superlock.c +++ b/src/test_superlock.c @@ -33,6 +33,17 @@ struct SuperlockBusy { }; typedef struct SuperlockBusy SuperlockBusy; +/* +** An instance of the following structure is allocated for each active +** superlock. The opaque handle returned by sqlite3demo_superlock() is +** actually a pointer to an instance of this structure. +*/ +struct Superlock { + sqlite3 *db; /* Database handle used to lock db */ + int bWal; /* True if db is a WAL database */ +}; +typedef struct Superlock Superlock; + /* ** The pCtx pointer passed to this function is actually a pointer to a ** SuperlockBusy structure. Invoke the busy-handler function encapsulated @@ -53,18 +64,18 @@ static int superlockBusyHandler(void *pCtx, int UNUSED){ ** If an error occurs, return an SQLite error code. The value of *pbWal ** is undefined in this case. */ -static int superlockIsWal(sqlite3 *db, int *pbWal){ +static int superlockIsWal(Superlock *pLock){ int rc; /* Return Code */ sqlite3_stmt *pStmt; /* Compiled PRAGMA journal_mode statement */ - rc = sqlite3_prepare(db, "PRAGMA main.journal_mode", -1, &pStmt, 0); + rc = sqlite3_prepare(pLock->db, "PRAGMA main.journal_mode", -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; - *pbWal = 0; + pLock->bWal = 0; if( SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zMode = (const char *)sqlite3_column_text(pStmt, 0); if( zMode && strlen(zMode)==3 && sqlite3_strnicmp("wal", zMode, 3)==0 ){ - *pbWal = 1; + pLock->bWal = 1; } } @@ -132,6 +143,23 @@ static int superlockWalLock( return rc; } +/* +** Release a superlock held on a database file. The argument passed to +** this function must have been obtained from a successful call to +** sqlite3demo_superlock(). +*/ +void sqlite3demo_superunlock(void *pLock){ + Superlock *p = (Superlock *)pLock; + if( p->bWal ){ + int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE; + sqlite3_file *fd = 0; + sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); + fd->pMethods->xShmLock(fd, 2, SQLITE_SHM_NLOCK-2, flags); + } + sqlite3_close(p->db); + sqlite3_free(p); +} + /* ** Obtain a superlock on the database file identified by zPath, using the ** locking primitives provided by VFS zVfs. If successful, SQLITE_OK is @@ -154,13 +182,17 @@ int sqlite3demo_superlock( void *pBusyArg, /* Context arg for busy handler */ void **ppLock /* OUT: Context to pass to superunlock() */ ){ - sqlite3 *db = 0; /* Database handle open on zPath */ SuperlockBusy busy = {0, 0, 0}; /* Busy handler wrapper object */ int rc; /* Return code */ + Superlock *pLock; + + pLock = sqlite3_malloc(sizeof(Superlock)); + if( !pLock ) return SQLITE_NOMEM; + memset(pLock, 0, sizeof(Superlock)); /* Open a database handle on the file to superlock. */ rc = sqlite3_open_v2( - zPath, &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs + zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs ); /* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not @@ -179,8 +211,8 @@ int sqlite3demo_superlock( if( rc==SQLITE_OK ){ busy.xBusy = xBusy; busy.pBusyArg = pBusyArg; - sqlite3_busy_handler(db, superlockBusyHandler, (void *)&busy); - rc = sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0); + sqlite3_busy_handler(pLock->db, superlockBusyHandler, (void *)&busy); + rc = sqlite3_exec(pLock->db, "BEGIN EXCLUSIVE", 0, 0, 0); } /* If the BEGIN EXCLUSIVE was executed successfully and this is a WAL @@ -193,34 +225,24 @@ int sqlite3demo_superlock( ** new WAL locks may conflict with the old. */ if( rc==SQLITE_OK ){ - int bWal; /* True for a WAL database, false otherwise */ - if( SQLITE_OK==(rc = superlockIsWal(db, &bWal)) && bWal ){ - rc = sqlite3_exec(db, "COMMIT", 0, 0, 0); + if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){ + rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0); if( rc==SQLITE_OK ){ - rc = superlockWalLock(db, &busy); + rc = superlockWalLock(pLock->db, &busy); } } } if( rc!=SQLITE_OK ){ - sqlite3_close(db); + sqlite3demo_superunlock(pLock); *ppLock = 0; }else{ - *ppLock = (void *)db; + *ppLock = pLock; } return rc; } -/* -** Release a superlock held on a database file. The argument passed to -** this function must have been obtained from a successful call to -** sqlite3demo_superlock(). -*/ -void sqlite3demo_superunlock(void *pLock){ - sqlite3_close((sqlite3 *)pLock); -} - /* ** End of example code. Everything below here is the test harness. ************************************************************************** diff --git a/test/superlock.test b/test/superlock.test index c022d35c78..41a55144a6 100644 --- a/test/superlock.test +++ b/test/superlock.test @@ -143,6 +143,15 @@ do_multiclient_test tn { list [catch {sqlite3demo_superlock unlock test.db} msg] $msg } {0 unlock} unlock + + + do_test 5.$tn.13 { sql1 { SELECT * FROM t1 } } {1 2 3 4 5 6} + do_test 5.$tn.14 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6} + do_test 5.$tn.15 { sqlite3demo_superlock unlock test.db } {unlock} + do_test 5.$tn.16 { unlock } {} + do_test 5.$tn.17 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6} + do_test 5.$tn.18 { sql1 { SELECT * FROM t1 } } {1 2 3 4 5 6} + do_test 5.$tn.19 { sql2 { SELECT * FROM t1 } } {1 2 3 4 5 6} } proc read_content {file} {