mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Fix an obscure problem with transactions written in "PRAGMA synchronous=full" mode on systems that do not support POWERSAFE_OVERWRITE causing an xSync() call to be omitted if the last frame written by a transaction is aligned to a sector boundary. This means that if a power failure or OS crash occurs very soon after such a transaction is committed, it may be lost following system recovery.
FossilOrigin-Name: 37de3eab67f12ae1ce5bc8d5e541c64fc6b1fd80
This commit is contained in:
17
manifest
17
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Improvements\sto\sthe\sinitialization\sof\sthe\spush-down\sautomoton\sfor\sthe\nLemon-generated\sparser.\s\sSmaller\sand\sfaster.
|
C Fix\san\sobscure\sproblem\swith\stransactions\swritten\sin\s"PRAGMA\ssynchronous=full"\smode\son\ssystems\sthat\sdo\snot\ssupport\sPOWERSAFE_OVERWRITE\scausing\san\sxSync()\scall\sto\sbe\somitted\sif\sthe\slast\sframe\swritten\sby\sa\stransaction\sis\saligned\sto\sa\ssector\sboundary.\sThis\smeans\sthat\sif\sa\spower\sfailure\sor\sOS\scrash\soccurs\svery\ssoon\safter\ssuch\sa\stransaction\sis\scommitted,\sit\smay\sbe\slost\sfollowing\ssystem\srecovery.
|
||||||
D 2016-05-24T00:40:54.799
|
D 2016-05-24T16:20:51.379
|
||||||
F Makefile.in f59e0763ff448719fc1bd25513882b0567286317
|
F Makefile.in f59e0763ff448719fc1bd25513882b0567286317
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7
|
F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7
|
||||||
@@ -394,7 +394,7 @@ F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
|||||||
F src/test3.c d2c9efd2985ff8f5502ffd3253156984778d77d8
|
F src/test3.c d2c9efd2985ff8f5502ffd3253156984778d77d8
|
||||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||||
F src/test6.c 2c014d4977efd6107ec9eef3dfdec56ac516f824
|
F src/test6.c a684b7abd01352ab50cb79c0bf727e6b3f381a3d
|
||||||
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
|
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
|
||||||
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
|
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
|
||||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||||
@@ -456,7 +456,7 @@ F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
|
|||||||
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
|
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
|
||||||
F src/vtab.c ce0f2ebb589b459b32c640b33af64bfa5b29aaf8
|
F src/vtab.c ce0f2ebb589b459b32c640b33af64bfa5b29aaf8
|
||||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||||
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
|
F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
|
||||||
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
|
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
|
||||||
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
|
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
|
||||||
F src/where.c 0e54a03d11d4e99ad25528f42ff4c9a6fa7a23da
|
F src/where.c 0e54a03d11d4e99ad25528f42ff4c9a6fa7a23da
|
||||||
@@ -1356,6 +1356,7 @@ F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278
|
|||||||
F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a
|
F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a
|
||||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||||
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
|
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
|
||||||
|
F test/walcrash4.test 2907eaa670156daf41bb865c30a08ad13088262c
|
||||||
F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b
|
F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b
|
||||||
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
||||||
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
||||||
@@ -1493,7 +1494,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 3c2a770549d5bb65fcd6cc684e0a0ae6d641ac68
|
P 3b28b68e232060f8b2fe2fe6fa478280da2006ff
|
||||||
R f0cfba4e984837df73820e425fc5291f
|
R 517787a46c326083f1c71f4f2bce6c10
|
||||||
U drh
|
U dan
|
||||||
Z 2da99ff99cbfd3def15eb678236b100e
|
Z 8b1bf46b6e26241c0a55d35f24f797fc
|
||||||
|
@@ -1 +1 @@
|
|||||||
3b28b68e232060f8b2fe2fe6fa478280da2006ff
|
37de3eab67f12ae1ce5bc8d5e541c64fc6b1fd80
|
24
src/test6.c
24
src/test6.c
@@ -215,7 +215,9 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TRACE_CRASHTEST
|
#ifdef TRACE_CRASHTEST
|
||||||
|
if( pFile ){
|
||||||
printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a"));
|
printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a"));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ppPtr = &g.pWriteList;
|
ppPtr = &g.pWriteList;
|
||||||
@@ -799,6 +801,27 @@ static int processDevSymArgs(
|
|||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** tclcmd: sqlite3_crash_now
|
||||||
|
**
|
||||||
|
** Simulate a crash immediately. This function does not return
|
||||||
|
** (writeListSync() calls exit(-1)).
|
||||||
|
*/
|
||||||
|
static int crashNowCmd(
|
||||||
|
void * clientData,
|
||||||
|
Tcl_Interp *interp,
|
||||||
|
int objc,
|
||||||
|
Tcl_Obj *CONST objv[]
|
||||||
|
){
|
||||||
|
if( objc!=1 ){
|
||||||
|
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
writeListSync(0, 1);
|
||||||
|
assert( 0 );
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** tclcmd: sqlite_crash_enable ENABLE
|
** tclcmd: sqlite_crash_enable ENABLE
|
||||||
**
|
**
|
||||||
@@ -1034,6 +1057,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
|
|||||||
#ifndef SQLITE_OMIT_DISKIO
|
#ifndef SQLITE_OMIT_DISKIO
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
||||||
|
Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
|
||||||
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
|
||||||
|
@@ -3109,16 +3109,21 @@ int sqlite3WalFrames(
|
|||||||
** past the sector boundary is written after the sync.
|
** past the sector boundary is written after the sync.
|
||||||
*/
|
*/
|
||||||
if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
|
if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
|
||||||
|
int bSync = 1;
|
||||||
if( pWal->padToSectorBoundary ){
|
if( pWal->padToSectorBoundary ){
|
||||||
int sectorSize = sqlite3SectorSize(pWal->pWalFd);
|
int sectorSize = sqlite3SectorSize(pWal->pWalFd);
|
||||||
w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
|
w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
|
||||||
|
bSync = (w.iSyncPoint==iOffset);
|
||||||
|
testcase( bSync );
|
||||||
while( iOffset<w.iSyncPoint ){
|
while( iOffset<w.iSyncPoint ){
|
||||||
rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
|
rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
iOffset += szFrame;
|
iOffset += szFrame;
|
||||||
nExtra++;
|
nExtra++;
|
||||||
}
|
}
|
||||||
}else{
|
}
|
||||||
|
if( bSync ){
|
||||||
|
assert( rc==SQLITE_OK );
|
||||||
rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
|
rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
75
test/walcrash4.test
Normal file
75
test/walcrash4.test
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# 2010 May 25
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
source $testdir/lock_common.tcl
|
||||||
|
source $testdir/wal_common.tcl
|
||||||
|
ifcapable !wal {finish_test ; return }
|
||||||
|
set testprefix walcrash4
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# At one point, if "PRAGMA synchronous=full" is set and the platform
|
||||||
|
# does not support POWERSAFE_OVERWRITE, and the last frame written to
|
||||||
|
# the wal file in a transaction is aligned with a sector boundary, the
|
||||||
|
# xSync() call was omitted.
|
||||||
|
#
|
||||||
|
# The following test verifies that this has been fixed.
|
||||||
|
#
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
PRAGMA autovacuum = 0;
|
||||||
|
PRAGMA page_size = 1024;
|
||||||
|
PRAGMA journal_mode = wal;
|
||||||
|
PRAGMA main.synchronous = full;
|
||||||
|
} {wal}
|
||||||
|
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
for {set nExtra 0} {$nExtra < 10} {incr nExtra} {
|
||||||
|
for {set i 0} {$i < 10} {incr i} {
|
||||||
|
do_test 1.nExtra=$nExtra.i=$i.1 {
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
|
||||||
|
set fd [open crash.tcl w]
|
||||||
|
puts $fd [subst -nocommands {
|
||||||
|
sqlite3_crash_enable 1
|
||||||
|
sqlite3_test_control_pending_byte $::sqlite_pending_byte
|
||||||
|
sqlite3 db test.db -vfs crash
|
||||||
|
db eval {
|
||||||
|
BEGIN;
|
||||||
|
CREATE TABLE t1(x UNIQUE);
|
||||||
|
}
|
||||||
|
for {set e 2} {[set e] < ($nExtra+2)} {incr e} {
|
||||||
|
db eval "CREATE TABLE t[set e] (x)"
|
||||||
|
}
|
||||||
|
db eval {
|
||||||
|
INSERT INTO t1 VALUES( randomblob(170000) );
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
sqlite3_crash_now
|
||||||
|
}]
|
||||||
|
close $fd
|
||||||
|
|
||||||
|
set r [catch { exec [info nameofexec] crash.tcl >@stdout } msg]
|
||||||
|
list $r $msg
|
||||||
|
} {1 {child process exited abnormally}}
|
||||||
|
|
||||||
|
do_execsql_test 1.nExtra=$nExtra.i=$i.2 {
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
} {1 ok}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
Reference in New Issue
Block a user