-C Cleanup\sthe\slocking-style\scode\sin\sos_unix.c.\s(CVS\s4837)
-D 2008-03-07T15:34:11
+C Correctly\shandle\sI/O\serrors\sthat\soccur\sduring\sOsUnlock().\s\sBefore\sthis\nfix,\san\sI/O\serror\sduring\sOsUnlock()\scould\slead\sto\sdatabase\scorruption.\nThat\sis\snot\sa\sserious\sproblem,\sthough,\ssince\serrors\sduring\sOsUnlock()\nare\snot\spossible\son\smost\ssystems.\s(CVS\s4838)
+D 2008-03-07T19:51:14
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in d521464011d6965bbda1b699f1850c6e33141c73
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/mutex_w32.c 6e197765f283815496193e78e9548b5d0e53b68e
F src/os.c 2f2753b8d33f79d169c43d6bb0b25b3c58fd33de
F src/os.h d04706d54a072c7a30ab9e346ad916ef28c842d5
-F src/os_common.h a66179e3b9a2686ba0f17a26d065d3e29202b7b8
+F src/os_common.h e8b748b2f2ecc8a498e50bfe5d8721f189c19d2a
F src/os_os2.c 10b23539e0050bdfc9f136242086a5c18c70c6f8
F src/os_os2.h c3f7d0af7e3453d1d7aa81b06c0a56f5a226530b
F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
-F src/os_unix.c bf339cd689054c8edc603c0209d91f62444c1477
+F src/os_unix.c 04ff58d84ae02d4ef732103455bfe36ce7780738
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c aa3f4bbee3b8c182d25a33fbc319f486857c12c1
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c d09885bb88e9868a5c322a0181d4022cf294d98b
+F src/pager.c 803d361f7aabfea1eebf8951916492c77d3781a2
F src/pager.h 8174615ffd14ccc2cad2b081b919a398fa95e3f9
F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d
F src/pragma.c e3f39f8576234887ecd0c1de43dc51af5855930c
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
F src/tclsqlite.c d95e0e74c7167b2807f9f4f73bf45f7c58096297
F src/test1.c c3d43a6bd299f3c115f6617af6715004819ca5cb
-F src/test2.c 355d5693ca3ee705548fa7f795592a37b2372b70
+F src/test2.c 89793e863188028b49bd259026a73820426539b3
F src/test3.c 5c7452038ab27aa698070799b10132f26cdd2a80
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
F test/intpkey.test 537669fd535f62632ca64828e435b9e54e8d677f
F test/io.test f2e9890eb3f159973fcb11008054596b0caeca4f
F test/ioerr.test 5382046b2ef19b9084652e7d2d1e82ab33c0deda
-F test/ioerr2.test e3d52c40f43f9b61da9b38951a737e7b84ebae96
+F test/ioerr2.test b9c9a0491a812707762a7c002876553be54d9969
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/join.test af0443185378b64878750aa1cf4b83c216f246b4
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/tableapi.test 4546eb710d979db023bfcc16b0c108b1557fcb43
F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
-F test/tester.tcl 7760c4101448e5595b2ee095e540643fa31a1610
+F test/tester.tcl 8f1df98df42667d05ee56ac4ba1ee58f9bb1e885
F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 9819cefbd7032fe6884c6c891e8e399000e0821f
-R 94e0b03717c8cb302d6990c16331816e
+P 40f55c09dbd31f861b9f9c7641cce92553d94e35
+R 862dd7b7066eb395b14356fb582df1d4
U drh
-Z c7afd0fbb52cbc7669e22683bc9d24e9
+Z aa58e6aa52b1bd4468d6e2d048a914af
-40f55c09dbd31f861b9f9c7641cce92553d94e35
\ No newline at end of file
+b4c1258edb4a40501d13c9da674d0366d5a8c694
\ No newline at end of file
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
-int sqlite3_io_error_hit = 0;
-int sqlite3_io_error_pending = 0;
-int sqlite3_io_error_persist = 0;
+int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+int sqlite3_io_error_benign = 0; /* True if errors are benign */
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE) \
- if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
- if( sqlite3_io_error_pending-- == 1 \
- || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
- { local_ioerr(); CODE; }
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+ || sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
static void local_ioerr(){
IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit = 1;
+ sqlite3_io_error_hit++;
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
}
#define SimulateDiskfullError(CODE) \
if( sqlite3_diskfull_pending ){ \
} \
}
#else
+#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif
struct flock lock;
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
+ int h;
assert( pFile );
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
return SQLITE_MISUSE;
}
enterMutex();
+ h = pFile->h;
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
assert( pLock->locktype==pFile->locktype );
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
if( locktype==SHARED_LOCK ){
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){
- /* This should never happen */
+ if( fcntl(h, F_SETLK, &lock)==(-1) ){
rc = SQLITE_IOERR_RDLOCK;
}
}
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
}
}
if( locktype==NO_LOCK ){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
+ pLock->cnt = 1;
}
}
** count reaches zero, close any other file descriptors whose close
** was deferred because of outstanding locks.
*/
- pOpen = pFile->pOpen;
- pOpen->nLock--;
- assert( pOpen->nLock>=0 );
- if( pOpen->nLock==0 && pOpen->nPending>0 ){
- int i;
- for(i=0; i<pOpen->nPending; i++){
- close(pOpen->aPending[i]);
+ if( rc==SQLITE_OK ){
+ pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 && pOpen->nPending>0 ){
+ int i;
+ for(i=0; i<pOpen->nPending; i++){
+ close(pOpen->aPending[i]);
+ }
+ free(pOpen->aPending);
+ pOpen->nPending = 0;
+ pOpen->aPending = 0;
}
- free(pOpen->aPending);
- pOpen->nPending = 0;
- pOpen->aPending = 0;
}
}
leaveMutex();
- pFile->locktype = locktype;
+ if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
- unsigned long long sharedLockByte; /* Byte offset of shared lock byte */
- const char *filePath; /* Name of the file */
+ unsigned long long sharedLockByte;
+ char *filePath;
};
struct ByteRangeLockPB2
sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
if( !pFile ) return SQLITE_OK;
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.412 2008/02/26 18:40:12 drh Exp $
+** @(#) $Id: pager.c,v 1.413 2008/03/07 19:51:14 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
if( !MEMDB ){
- if( pPager->fd->pMethods ){
- osUnlock(pPager->fd, NO_LOCK);
- }
+ int rc = osUnlock(pPager->fd, NO_LOCK);
+ if( rc ) pager_error(pPager, rc);
pPager->dbSize = -1;
IOTRACE(("UNLOCK %p\n", pPager))
** cache can be discarded and the error code safely cleared.
*/
if( pPager->errCode ){
- pPager->errCode = SQLITE_OK;
+ if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
pager_reset(pPager);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
}
if( rc!=SQLITE_OK ){
pager_unlock(pPager);
- return ((rc==SQLITE_NOMEM||rc==SQLITE_IOERR_NOMEM)?rc:SQLITE_BUSY);
+ switch( rc ){
+ case SQLITE_NOMEM:
+ case SQLITE_IOERR_UNLOCK:
+ case SQLITE_IOERR_NOMEM:
+ return rc;
+ default:
+ return SQLITE_BUSY;
+ }
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test2.c,v 1.53 2008/02/18 14:47:34 drh Exp $
+** $Id: test2.c,v 1.54 2008/03/07 19:51:14 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
extern int sqlite3_io_error_persist;
extern int sqlite3_io_error_pending;
extern int sqlite3_io_error_hit;
+ extern int sqlite3_io_error_hardhit;
extern int sqlite3_diskfull_pending;
extern int sqlite3_diskfull;
extern int sqlite3_pager_n_sort_bucket;
(char*)&sqlite3_io_error_persist, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_io_error_hit",
(char*)&sqlite3_io_error_hit, TCL_LINK_INT);
+ Tcl_LinkVar(interp, "sqlite_io_error_hardhit",
+ (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_diskfull_pending",
(char*)&sqlite3_diskfull_pending, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_diskfull",
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
-# $Id: ioerr2.test,v 1.6 2007/09/12 17:01:45 danielk1977 Exp $
+# $Id: ioerr2.test,v 1.7 2008/03/07 19:51:15 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# connection. Otherwise, try a ROLLBACK, in case a transaction
# is still active.
set rc [catch {execsql {PRAGMA integrity_check}} msg]
- if {$rc && $msg eq "disk I/O error"} {
+ if {$rc && ($msg eq "disk I/O error" || $msg eq "database is locked")} {
db close
sqlite3 db test.db
set refcnt 0
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
-# $Id: tester.tcl,v 1.105 2008/02/16 16:21:46 drh Exp $
+# $Id: tester.tcl,v 1.106 2008/03/07 19:51:15 drh Exp $
set tcl_precision 15
# there are at least N IO operations performed by SQLite as
# a result of the script, the Nth will fail.
do_test $testname.$n.3 {
+ set ::sqlite_io_error_hit 0
+ set ::sqlite_io_error_hardhit 0
set r [catch $::ioerrorbody msg]
+ set ::errseen $r
set rc [sqlite3_errcode $::DB]
if {$::ioerropts(-erc)} {
# If we are in extended result code mode, make sure all of the
}
set s [expr $::sqlite_io_error_hit==0]
+ if {$::sqlite_io_error_hit>$::sqlite_io_error_hardhit && $r==0} {
+ set r 1
+ }
set ::sqlite_io_error_hit 0
# One of two things must have happened. either
# 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 && $::ioerropts(-cksum)} {
+ if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} {
do_test $testname.$n.4 {
catch {db close}
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
} $checksum
}
+ set ::sqlite_io_error_hardhit 0
set ::sqlite_io_error_pending 0
if {[info exists ::ioerropts(-cleanup)]} {
catch $::ioerropts(-cleanup)