From: danielk1977 Date: Fri, 20 Jan 2006 16:32:04 +0000 (+0000) Subject: Fix another couple of IO or malloc() failure problems in a shared-cache context.... X-Git-Tag: version-3.6.10~3185 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=97a227c996db2c162a4332aa365b86954687ecd9;p=thirdparty%2Fsqlite.git Fix another couple of IO or malloc() failure problems in a shared-cache context. (CVS 2982) FossilOrigin-Name: 7e34163a65a5842ecc50a14a9d60601e7c9d3249 --- diff --git a/manifest b/manifest index 7d13cd8bd5..f4677882cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sand\stest\sthe\sprocessing\sof\ssqlite3_result_error()\swithing\saggregate\nfunctions.\s\sAllow\serrors\sto\scome\sfrom\sthe\sstep\sfunction\s(a\snew\ncapability).\s\sTicket\s#1632.\s(CVS\s2981) -D 2006-01-20T15:45:36 +C Fix\sanother\scouple\sof\sIO\sor\smalloc()\sfailure\sproblems\sin\sa\sshared-cache\scontext.\s(CVS\s2982) +D 2006-01-20T16:32:04 F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -34,7 +34,7 @@ F src/alter.c 90b779cf00489535cab6490df6dc050f40e4e874 F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a F src/attach.c 0081040e9a5d13669b6712e947688c10f030bfc1 F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2 -F src/btree.c e8ff8d76a412299cad1c9a2c4e1fd15ad48bae27 +F src/btree.c 8b890e64b0ad7c510635244b75d65a97ee9f26ad F src/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184 F src/build.c 15224e2fd348ad32b9044aaa5bdc912e4067da15 F src/callback.c 1bf497306c32229114f826707054df7ebe10abf2 @@ -59,7 +59,7 @@ F src/os_unix.c a242a9458b08f01fa11d42b23bcdb89a3fbf2a68 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 98e4e38db7d4a00647b2bb1c60d28b7ca5034c03 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 49fab8c32de2419cb549220d285c6399bc0d899e +F src/pager.c 39bf1957f8531c9056c8659048a4cdd949439d66 F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c F src/pragma.c 4496cc77dc35824e1c978c3d1413b8a5a4c777d3 @@ -90,8 +90,8 @@ F src/vacuum.c 3865673cc66acd0717ecd517f6b8fdb2a5e7924b F src/vdbe.c 9eceb866b8197d25d07f700e16b1a50638d4bd6e F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 F src/vdbeInt.h eb3f86ab08ef11635bc78eb88c3ff13f923c233b -F src/vdbeapi.c b5a3eacce266a657cdc0fc740b60ba480fb88649 -F src/vdbeaux.c d9a757ed4e3eefc54408226cb781694059fe2b39 +F src/vdbeapi.c 75eabedc09b3b2a6f2d256f85704b8b0cc0f50fa +F src/vdbeaux.c 9d92640082c632ab2a48fa0b1763390a78573607 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c 2034e93b32c14bda6e306bb54e3a8e930b963027 F src/where.c 5215507b232e718606e0014f999912d53de32a70 @@ -189,7 +189,7 @@ F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9 F test/main.test b12f01d49a5c805a33fa6c0ef168691f63056e79 F test/malloc.test ce6d1e7e79f9db967b51e1975b50760af66db90d F test/malloc2.test e6e321db96d6c94cb18bf82ad7215070c41e624e -F test/malloc3.test 1cf2376c9495973608c021efaefb25e71bd6e21f +F test/malloc3.test 5494b3fac35a2362584c97dc5655c2c3227c798a F test/malloc4.test 2e29d155eb4b4808019ef47eeedfcbe9e09e0f05 F test/malloc5.test 7425272e263325fda7d32cb55706e52b5c09e7e0 F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8 @@ -228,7 +228,7 @@ F test/select7.test 1bf795b948c133a15a2a5e99d3270e652ec58ce6 F test/server1.test e328b8e641ba8fe9273132cfef497383185dc1f5 F test/shared.test 9982a65ccf3f4eee844a19f3ab0bcd7a158a76e5 F test/shared2.test 909fc0f0277684ed29cc1b36c8e159188aec7f28 -F test/shared_err.test dea32ad1ce72c1aa88a4671b5de3900961f6c687 +F test/shared_err.test f72c9fbe1802500f0d97e768f947ae5c703c0152 F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5 F test/subquery.test ae324ee928c5fb463a3ce08a8860d6e7f1ca5797 F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2 @@ -344,7 +344,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 97491d4eb5fc24d8f5cc7605db844359ecc6a818 -R 0ac1c3b7951d8503eabc2e4f37bf1aac -U drh -Z 64f4b8a9886c6294a59c365b44cd61fd +P fd4a6bb1ac94d085dda247799c0a5c64aaeec046 +R bde9ce22812627a378f8978bb7879372 +U danielk1977 +Z c8dd5ea23e29760f9b39f58f5d5d0fb8 diff --git a/manifest.uuid b/manifest.uuid index 103b23698e..5e2ee2f34c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fd4a6bb1ac94d085dda247799c0a5c64aaeec046 \ No newline at end of file +7e34163a65a5842ecc50a14a9d60601e7c9d3249 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 9471665b3c..cd558f7f43 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.303 2006/01/20 10:55:05 danielk1977 Exp $ +** $Id: btree.c,v 1.304 2006/01/20 16:32:04 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -506,6 +506,8 @@ struct BtLock { #else +static void releasePage(MemPage *pPage); + /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. @@ -540,6 +542,8 @@ static int saveCursorPosition(BtCursor *pCur){ assert( !pCur->pPage->intKey || !pCur->pKey ); /* Todo: Should we drop the reference to pCur->pPage here? */ + releasePage(pCur->pPage); + pCur->pPage = 0; if( rc==SQLITE_OK ){ pCur->eState = CURSOR_REQUIRESEEK; @@ -2617,12 +2621,15 @@ int sqlite3BtreeCommitStmt(Btree *p){ ** will result in an error. */ int sqlite3BtreeRollbackStmt(Btree *p){ - int rc; + int rc = SQLITE_OK; BtShared *pBt = p->pBt; - if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK; - rc = sqlite3pager_stmt_rollback(pBt->pPager); - assert( countWriteCursors(pBt)==0 ); - pBt->inStmt = 0; + sqlite3MallocDisallow(); + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3pager_stmt_rollback(pBt->pPager); + assert( countWriteCursors(pBt)==0 ); + pBt->inStmt = 0; + } + sqlite3MallocAllow(); return rc; } @@ -3174,9 +3181,8 @@ static int moveToRoot(BtCursor *pCur){ BtShared *pBt = pCur->pBtree->pBt; restoreOrClearCursorPosition(pCur, 0); - assert( pCur->pPage ); pRoot = pCur->pPage; - if( pRoot->pgno==pCur->pgnoRoot ){ + if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); }else{ if( @@ -3443,7 +3449,7 @@ int sqlite3BtreeEof(BtCursor *pCur){ */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; - MemPage *pPage = pCur->pPage; + MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE rc = restoreOrClearCursorPosition(pCur, 1); @@ -3456,9 +3462,10 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ return SQLITE_OK; } pCur->skip = 0; -#endif +#endif assert( pRes!=0 ); + pPage = pCur->pPage; if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; diff --git a/src/pager.c b/src/pager.c index 9d52df3ed3..29a5dbf48c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.246 2006/01/20 10:55:05 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.247 2006/01/20 16:32:04 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -2693,10 +2693,15 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ i64 fileSize; - if( sqlite3OsFileSize(pPager->fd,&fileSize)!=SQLITE_OK - || fileSize>=pgno*pPager->pageSize ){ + int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize); + if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ + /* An IO error occured in one of the the sqlite3OsSeek() or + ** sqlite3OsRead() calls above. Unreference the page and then + ** set it's page number to 0 (0 means "not a page"). + */ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); - return pager_error(pPager, rc); + pPg->pgno = 0; + return rc; }else{ clear_simulated_io_error(); memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4b5c13642e..a8d76b26b8 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -241,7 +241,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ } #endif - sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); + sqlite3Error(p->db, rc, 0); p->rc = sqlite3ApiExit(p->db, p->rc); return rc; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 4c61e7c192..d9c191d54e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1242,6 +1242,8 @@ int sqlite3VdbeHalt(Vdbe *p){ /* We are forced to roll back the active transaction. Before doing ** so, abort any other statements this handle currently has active. */ + abortOtherActiveVdbes(p); + sqlite3RollbackAll(db); db->autoCommit = 1; } } @@ -1264,12 +1266,12 @@ int sqlite3VdbeHalt(Vdbe *p){ return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; - rollbackAll(db, p); + sqlite3RollbackAll(db); }else{ sqlite3CommitInternalChanges(db); } }else{ - rollbackAll(db, p); + sqlite3RollbackAll(db); } }else if( !xFunc ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ @@ -1277,7 +1279,8 @@ int sqlite3VdbeHalt(Vdbe *p){ }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ - rollbackAll(db, p); + abortOtherActiveVdbes(p); + sqlite3RollbackAll(db); db->autoCommit = 1; } } @@ -1359,8 +1362,9 @@ int sqlite3VdbeReset(Vdbe *p){ */ if( p->pc>=0 ){ if( p->zErrMsg ){ - sqlite3Error(p->db, p->rc, "%s", p->zErrMsg); - sqliteFree(p->zErrMsg); + sqlite3* db = p->db; + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3FreeX); + db->errCode = p->rc; p->zErrMsg = 0; }else if( p->rc ){ sqlite3Error(p->db, p->rc, 0); diff --git a/test/malloc3.test b/test/malloc3.test index bfdf3727a5..6de89c5d40 100644 --- a/test/malloc3.test +++ b/test/malloc3.test @@ -13,7 +13,7 @@ # correctly. The emphasis of these tests are the _prepare(), _step() and # _finalize() calls. # -# $Id: malloc3.test,v 1.7 2006/01/20 10:55:05 danielk1977 Exp $ +# $Id: malloc3.test,v 1.8 2006/01/20 16:32:04 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -492,13 +492,27 @@ TEST 32 { sqlite3_step $::STMT32 } {SQLITE_ROW} } -puts [execsql {SELECT * FROM ghi}] } -SQL { - BEGIN; - INSERT INTO ghi SELECT * FROM ghi; - COMMIT; +SQL BEGIN +TEST 33 { + do_test $testid { + execsql {SELECT * FROM ghi} + } {a b c 1 2 3} +} +SQL -norollback { + -- There is a unique index on ghi(g), so this statement may not cause + -- an automatic ROLLBACK. Hence the "-norollback" switch. + INSERT INTO ghi SELECT '2'||g, h, i FROM ghi; +} +TEST 34 { + if {[info exists ::STMT32]} { + do_test $testid { + sqlite3_finalize $::STMT32 + } {SQLITE_OK} + unset ::STMT32 + } } +SQL COMMIT # # End of test program declaration @@ -630,7 +644,7 @@ proc run_test {arglist {pcstart 0} {iFailStart 1}} { # Turn of the Tcl interface's prepared statement caching facility. db cache size 0 -run_test $::run_test_script 76 6 +run_test $::run_test_script # run_test [lrange $::run_test_script 0 3] 0 63 sqlite_malloc_fail 0 db close diff --git a/test/shared_err.test b/test/shared_err.test index 16d629d149..cdbc98a21f 100644 --- a/test/shared_err.test +++ b/test/shared_err.test @@ -13,7 +13,7 @@ # cache context. What happens to connection B if one connection A encounters # an IO-error whilst reading or writing the file-system? # -# $Id: shared_err.test,v 1.1 2006/01/20 10:55:05 danielk1977 Exp $ +# $Id: shared_err.test,v 1.2 2006/01/20 16:32:05 danielk1977 Exp $ proc skip {args} {} @@ -28,7 +28,6 @@ ifcapable !shared_cache||!subquery { } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] -skip \ do_ioerr_test shared_ioerr-1 -tclprep { sqlite3 db2 test.db execsql { @@ -52,7 +51,7 @@ do_ioerr_test shared_ioerr-1 -tclprep { SELECT * FROM t1; DELETE FROM t1 WHERE a<100; } -cleanup { - do_test shared_ioerr-$n.cleanup.1 { + do_test shared_ioerr-1.$n.cleanup.1 { set res [catchsql { SELECT * FROM t1; } db2] @@ -131,6 +130,44 @@ do_ioerr_test shared_ioerr-2 -tclprep { db2 close } +# This test is designed to provoke an IO error when a cursor position is +# "saved" (because another cursor is going to modify the underlying table). +# +do_ioerr_test shared_ioerr-3 -tclprep { + sqlite3 db2 test.db + execsql { + PRAGMA read_uncommitted = 1; + BEGIN; + CREATE TABLE t1(a, b, UNIQUE(a, b)); + } db2 + for {set i 0} {$i < 5} {incr i} { + set a [string repeat $i 10] + set b [string repeat $i 2000] + execsql {INSERT INTO t1 VALUES($a, $b)} db2 + } + execsql {COMMIT} db2 + set ::DB2 [sqlite3_connection_pointer db2] + set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] + sqlite3_step $::STMT ;# Cursor points at 0000000000 + sqlite3_step $::STMT ;# Cursor points at 1111111111 +} -tclbody { + execsql { + INSERT INTO t1 VALUES(6, NULL); + } +} -cleanup { + do_test shared_ioerr-3.$n.cleanup.1 { + sqlite3_step $::STMT + } {SQLITE_ROW} + do_test shared_ioerr-3.$n.cleanup.2 { + sqlite3_column_text $::STMT 0 + } {2222222222} + do_test shared_ioerr-3.$n.cleanup.3 { + sqlite3_finalize $::STMT + } {SQLITE_OK} +# db2 eval {select * from sqlite_master} + db2 close +} + catch {db close} sqlite3_enable_shared_cache $::enable_shared_cache finish_test