From: danielk1977 Date: Mon, 5 May 2008 16:23:55 +0000 (+0000) Subject: If an IO error occurs while locking the database and checking the cache validity... X-Git-Tag: version-3.6.10~1094 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=52b472aebf017ff3ade8e921b0ff91a0e34bdc52;p=thirdparty%2Fsqlite.git If an IO error occurs while locking the database and checking the cache validity, unlock the database before returning. Ticket #3030. (CVS 5083) FossilOrigin-Name: 4ad1809192b616d1c12499825bcd0967dea76864 --- diff --git a/manifest b/manifest index de362930cc..2c51680bcf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sleaking\spage\sreferences\safter\san\sIO\serror\sis\sencountered.\s(CVS\s5082) -D 2008-05-05T15:26:51 +C If\san\sIO\serror\soccurs\swhile\slocking\sthe\sdatabase\sand\schecking\sthe\scache\svalidity,\sunlock\sthe\sdatabase\sbefore\sreturning.\sTicket\s#3030.\s(CVS\s5083) +D 2008-05-05T16:23:55 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -122,7 +122,7 @@ F src/os_common.h e8b748b2f2ecc8a498e50bfe5d8721f189c19d2a F src/os_os2.c 41015b3fa91568761eb10cbf6ca27a0624ba0bda F src/os_unix.c 8cf512c4321c3114f053dc9eaae394db2dc03ebe F src/os_win.c 3a60bddd07ea6f8adb2314dd5996ac97b988f403 -F src/pager.c 2d495e9a439e7f5db12f02cd8efe6ae417bff26a +F src/pager.c 5ac6728cf575afd87f8c5afe88bb768d3a641e34 F src/pager.h 4f051fd856de6fd3c19aef5f82eace54122b9173 F src/parse.y fc4bd35c6088901f7c8daead26c6fb11c87d22e7 F src/pragma.c 2e4bb2e76e48a32750529fdc4bfe86ac5f54e01b @@ -458,7 +458,7 @@ F test/tableapi.test 791f7e3891d9b70bdb43b311694bf5e9befcbc34 F test/tclsqlite.test 3dfb48f46de4353376fad835390b493ba066b4dc F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 -F test/tester.tcl 3f476ad2a7d8532b8de3ad7b0ed95995ee78f45b +F test/tester.tcl 392890469221c2410759bb048bef99f5e20741a6 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7 F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 @@ -634,7 +634,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 2275fc6ee06b17da5808cecfa5570ac6439eaf74 -R 6d76420da4b019df82bc43b649a5cfb1 +P 198c395b01140ef48b6913c00188ba7168bfb081 +R 6e0e093a0f17c8e821e8c74c11e266a3 U danielk1977 -Z 562dc8fb914e4c15e377eee1cc4d777b +Z 67d910e4d419f070999a506a26c6b1be diff --git a/manifest.uuid b/manifest.uuid index 19c861ab8d..ce39a19acb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -198c395b01140ef48b6913c00188ba7168bfb081 \ No newline at end of file +4ad1809192b616d1c12499825bcd0967dea76864 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index fadcf29dc9..fca3d3bc9e 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.438 2008/05/01 17:16:53 drh Exp $ +** @(#) $Id: pager.c,v 1.439 2008/05/05 16:23:55 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -3401,6 +3401,7 @@ static int pagerSharedLock(Pager *pPager){ if( !pPager->noReadlock ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ + assert( pPager->state==PAGER_UNLOCK ); return pager_error(pPager, rc); } assert( pPager->state>=SHARED_LOCK ); @@ -3411,7 +3412,8 @@ static int pagerSharedLock(Pager *pPager){ */ rc = hasHotJournal(pPager); if( rc<0 ){ - return SQLITE_IOERR_NOMEM; + rc = SQLITE_IOERR_NOMEM; + goto failed; } if( rc==1 || isHot ){ /* Get an EXCLUSIVE lock on the database file. At this point it is @@ -3428,8 +3430,8 @@ static int pagerSharedLock(Pager *pPager){ if( pPager->statefd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - return pager_error(pPager, rc); + rc = pager_error(pPager, rc); + goto failed; } pPager->state = PAGER_EXCLUSIVE; } @@ -3463,15 +3465,12 @@ static int pagerSharedLock(Pager *pPager){ } } if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - switch( rc ){ - case SQLITE_NOMEM: - case SQLITE_IOERR_UNLOCK: - case SQLITE_IOERR_NOMEM: - return rc; - default: - return SQLITE_BUSY; + if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK + && rc!=SQLITE_IOERR_NOMEM + ){ + rc = SQLITE_BUSY; } + goto failed; } pPager->journalOpen = 1; pPager->journalStarted = 0; @@ -3484,7 +3483,8 @@ static int pagerSharedLock(Pager *pPager){ */ rc = pager_playback(pPager, 1); if( rc!=SQLITE_OK ){ - return pager_error(pPager, rc); + rc = pager_error(pPager, rc); + goto failed; } assert(pPager->state==PAGER_SHARED || (pPager->exclusiveMode && pPager->state>PAGER_SHARED) @@ -3512,14 +3512,15 @@ static int pagerSharedLock(Pager *pPager){ sqlite3PagerPagecount(pPager); if( pPager->errCode ){ - return pPager->errCode; + rc = pPager->errCode; + goto failed; } if( pPager->dbSize>0 ){ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); if( rc!=SQLITE_OK ){ - return rc; + goto failed; } }else{ memset(dbFileVers, 0, sizeof(dbFileVers)); @@ -3536,6 +3537,11 @@ static int pagerSharedLock(Pager *pPager){ } } + failed: + if( rc!=SQLITE_OK ){ + /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */ + pager_unlock(pPager); + } return rc; } diff --git a/test/tester.tcl b/test/tester.tcl index b7039770e5..369ad996e3 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,7 +11,7 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.117 2008/05/05 15:26:51 danielk1977 Exp $ +# $Id: tester.tcl,v 1.118 2008/05/05 16:23:55 danielk1977 Exp $ # # What for user input before continuing. This gives an opportunity @@ -684,10 +684,11 @@ proc do_ioerr_test {testname args} { expr { ($s && !$r && !$q) || (!$s && $r && $q) } } {1} + # Check that no page references were leaked. There should be + # a single reference if there is still an active transaction, + # or zero otherwise. + # if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-ckrefcount)} { - # Check that no page references were leaked. There should be - # a single reference if there is still an active transaction, - # or zero otherwise. do_test $testname.$n.4 { set bt [btree_from_db db] db_enter db @@ -697,8 +698,30 @@ proc do_ioerr_test {testname args} { } [expr {[sqlite3_get_autocommit db]?0:1}] } + # If there is an open database handle and no open transaction, + # and the pager is not running in exclusive-locking mode, + # check that the pager is in "unlocked" state. Theoretically, + # if a call to xUnlock() failed due to an IO error the underlying + # file may still be locked. + # + ifcapable pragma { + if { [info commands db] ne "" + && [db one {pragma locking_mode}] eq "normal" + && [sqlite3_get_autocommit db] + } { + do_test $testname.$n.5 { + set bt [btree_from_db db] + db_enter db + array set stats [btree_pager_stats $bt] + db_leave db + set stats(state) + } 0 + } + } + # If an IO error occured, then the checksum of the database should # be the same as before the script that caused the IO error was run. + # if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} { do_test $testname.$n.5 { catch {db close}