From 96b958afae945a9841b54e48b4f8fa494a732c50 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 5 Oct 2010 17:02:47 +0000 Subject: [PATCH] Have the pager change to at least WRITER_CACHEMOD state before marking any pages as dirty (instead of immediately after). Otherwise, if an error occurs, the pager may be left in WRITER_LOCKED state with dirty pages in the cache. FossilOrigin-Name: 471a4efbb7e5e32b144b2e2128337a6af950b8f5 --- manifest | 26 ++++++++------------------ manifest.uuid | 2 +- src/pager.c | 32 ++++++++++++++++---------------- test/malloc3.test | 2 +- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 4f18c4acff..3776d565ab 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C If\swalLockExclusive()\sfails\sfor\sreasons\sother\sthan\sSQLITE_BUSY\sinside\sof\nwalRestartLog()\sthen\spropagate\sthat\serror\sback\sup\sto\sthe\sapplication. -D 2010-10-05T15:41:06 +C Have\sthe\spager\schange\sto\sat\sleast\sWRITER_CACHEMOD\sstate\sbefore\smarking\sany\spages\sas\sdirty\s(instead\sof\simmediately\safter).\sOtherwise,\sif\san\serror\soccurs,\sthe\spager\smay\sbe\sleft\sin\sWRITER_LOCKED\sstate\swith\sdirty\spages\sin\sthe\scache. +D 2010-10-05T17:02:48 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,7 +161,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c ae27ac760ad9c79f0fa3c96bfb31975c45aa704d F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad -F src/pager.c 4760042267a002216c208aeaa7fc6d0a85df94a5 +F src/pager.c 6c6dde871c540438862d5169650544d843e5b7f7 F src/pager.h 8167a1e720d0b7a2790079007128e594010220ad F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa @@ -516,7 +513,7 @@ F test/lookaside.test 382e7bc2fab23d902c8eafb1b9ed7ababfff75a6 F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252 F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 F test/malloc.test 927e6c8668a1d48c23aa6189bda02aff5a1b83de -F test/malloc3.test 4bc57f850b212f706f3e1b37c4eced1d5a727cd1 +F test/malloc3.test 4128b1e6ffa506103b278ad97af89174f310c7ca F test/malloc4.test 957337613002b7058a85116493a262f679f3a261 F test/malloc5.test 4d16d1bb26d2deddd7c4f480deec341f9b2d0e22 F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 @@ -875,14 +872,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 4afdf9705a7c2b67aea31c5d51b9c295867d62d1 -R 0b598db9d15663b9eac0eb9608cf219e -U drh -Z 4912e1202186b273f4e8ef7f3dd0f8e0 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFMq0cVoxKgR168RlERAvcDAJ4iltbS62O/tU0jHhSrStG3EtEbrQCfTkH/ -ai1cUz4PA5aKqP9WWoZrWbA= -=vRiW ------END PGP SIGNATURE----- +P 04dcba6b3379d2168609950ed919c8f743705333 +R bdadc2754b2c663c0809da21888af26a +U dan +Z 210a2f6d2e9b55ba1bed3a89142a775f diff --git a/manifest.uuid b/manifest.uuid index a44d337d5a..415217164a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -04dcba6b3379d2168609950ed919c8f743705333 \ No newline at end of file +471a4efbb7e5e32b144b2e2128337a6af950b8f5 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 1284f1ae74..2faeb15b28 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5205,29 +5205,29 @@ static int pager_write(PgHdr *pPg){ CHECK_PAGE(pPg); + /* The journal file needs to be opened. Higher level routines have already + ** obtained the necessary locks to begin the write-transaction, but the + ** rollback journal might not yet be open. Open it now if this is the case. + ** + ** This is done before calling sqlite3PcacheMakeDirty() on the page. + ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then + ** an error might occur and the pager would end up in WRITER_LOCKED state + ** with pages marked as dirty in the cache. + */ + if( pPager->eState==PAGER_WRITER_LOCKED ){ + rc = pager_open_journal(pPager); + if( rc!=SQLITE_OK ) return rc; + } + assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); + assert( assert_pager_state(pPager) ); + /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ sqlite3PcacheMakeDirty(pPg); if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){ assert( !pagerUseWal(pPager) ); - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); }else{ - - /* If we get this far, it means that the page needs to be - ** written to the transaction journal or the checkpoint journal - ** or both. - ** - ** Higher level routines have already obtained the necessary locks - ** to begin the write-transaction, but the rollback journal might not - ** yet be open. Open it now if this is the case. - */ - if( pPager->eState==PAGER_WRITER_LOCKED ){ - rc = pager_open_journal(pPager); - if( rc!=SQLITE_OK ) return rc; - } - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); - assert( assert_pager_state(pPager) ); /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to diff --git a/test/malloc3.test b/test/malloc3.test index 0046798eff..73d2d39642 100644 --- a/test/malloc3.test +++ b/test/malloc3.test @@ -655,7 +655,7 @@ sqlite3 db test.db sqlite3_extended_result_codes db 1 set ::DB [sqlite3_connection_pointer db] -# Turn of the Tcl interface's prepared statement caching facility in +# Turn off the Tcl interface's prepared statement caching facility in # the new connnection. Then run the tests with "transient" malloc failures. db cache size 0 run_test $::run_test_script 0 -- 2.47.2