Index: src/wal.c ================================================================== --- src/wal.c +++ src/wal.c @@ -2069,10 +2069,16 @@ /* The header was successfully read. Return zero. */ return 0; } +/* +** This is the value that walTryBeginRead returns when it needs to +** be retried. +*/ +#define WAL_RETRY (-1) + /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the ** wal-index from the WAL before returning. ** @@ -2147,23 +2153,20 @@ rc = SQLITE_CANTOPEN_BKPT; } if( pWal->bUnlocked ){ if( rc!=SQLITE_OK ){ walIndexClose(pWal, 0); + pWal->bUnlocked = 0; + assert( pWal->nWiData>0 && pWal->apWiData[0]==0 ); + if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; } pWal->exclusiveMode = WAL_NORMAL_MODE; } return rc; } -/* -** This is the value that walTryBeginRead returns when it needs to -** be retried. -*/ -#define WAL_RETRY (-1) - /* ** Open an "unlocked" transaction. An unlocked transaction is a read ** transaction used by a read-only client in cases where the *-shm ** file cannot be mapped and its contents cannot be trusted. It is ** assumed that the *-wal file has been read and that a wal-index Index: test/walro2.test ================================================================== --- test/walro2.test +++ test/walro2.test @@ -333,9 +333,62 @@ do_test 5.3 { code1 { db close } code1 { tvfs delete } } {} + #----------------------------------------------------------------------- + # + # + catch { code1 { db close } } + catch { code2 { db2 close } } + catch { code3 { db3 close } } + + do_test 6.1 { + code1 { forcedelete test.db } + code1 { sqlite3 db test.db } + sql1 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('hello'); + INSERT INTO t1 VALUES('world'); + INSERT INTO t1 VALUES('!'); + INSERT INTO t1 VALUES('world'); + INSERT INTO t1 VALUES('hello'); + } + + forcecopy test.db test.db2 + forcecopy test.db-wal test.db2-wal + forcecopy test.db-shm test.db2-shm + + code1 { db close } + } {} + + do_test 6.2 { + code1 { + set ::nRem 5 + proc handle_read {op args} { + if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} { + incr ::nRem -1 + if {$::nRem==0} { + code2 { sqlite3 db2 test.db2 } + sql2 { PRAGMA wal_checkpoint = truncate } + } + } + return "SQLITE_OK" + } + testvfs tvfs -fullshm 1 + + tvfs filter xRead + tvfs script handle_read + + sqlite3 db file:test.db2?readonly_shm=1&vfs=tvfs + db eval { SELECT * FROM t1 } + } + } {hello world ! world hello} + do_test 6.3 { + code1 { db close } + code1 { tvfs delete } + } {} } finish_test