aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-03-26 20:43:05 +0000
committerdrh <drh@noemail.net>2018-03-26 20:43:05 +0000
commitfd72563d0aaf09857ab37c38ff4ac0d3b5df92e6 (patch)
tree99eb2843aa103efa825b5328812214340f3872a2 /src
parentf0119b2e1bfc0457b61d4b00d73bafef9274cf17 (diff)
downloadsqlite-fd72563d0aaf09857ab37c38ff4ac0d3b5df92e6.tar.gz
sqlite-fd72563d0aaf09857ab37c38ff4ac0d3b5df92e6.zip
Avoid a race condition that might cause a busy_timeout to last longer than
it should. FossilOrigin-Name: b81960561b47a1b49646f2f8870dd0684dc4ca7c0b9e11076fd713de66b75972
Diffstat (limited to 'src')
-rw-r--r--src/btree.c1
-rw-r--r--src/os_unix.c11
-rw-r--r--src/pager.c14
-rw-r--r--src/pager.h5
4 files changed, 24 insertions, 7 deletions
diff --git a/src/btree.c b/src/btree.c
index 6bcf379d6..402503916 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -3373,6 +3373,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
+ sqlite3PagerResetLockTimeout(pBt->pPager);
if( rc==SQLITE_OK ){
if( p->inTrans==TRANS_NONE ){
diff --git a/src/os_unix.c b/src/os_unix.c
index ac4ec2f2f..2b9c117e3 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1490,18 +1490,15 @@ static int osSetPosixAdvisoryLock(
unixFile *pFile /* Structure holding timeout value */
){
int rc = osFcntl(h,F_SETLK,pLock);
- if( rc<0 && pFile->iBusyTimeout>0 ){
+ while( rc<0 && pFile->iBusyTimeout>0 ){
/* On systems that support some kind of blocking file lock with a timeout,
** make appropriate changes here to invoke that blocking file lock. On
** generic posix, however, there is no such API. So we simply try the
** lock once every millisecond until either the timeout expires, or until
** the lock is obtained. */
- do{
- usleep(1000);
- rc = osFcntl(h,F_SETLK,pLock);
- pFile->iBusyTimeout--;
- }while( rc<0 && pFile->iBusyTimeout>0 );
- pFile->iBusyTimeout = 0;
+ usleep(1000);
+ rc = osFcntl(h,F_SETLK,pLock);
+ pFile->iBusyTimeout--;
}
return rc;
}
diff --git a/src/pager.c b/src/pager.c
index 55f90057e..85d1845e9 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -5693,6 +5693,7 @@ void sqlite3PagerUnrefPageOne(DbPage *pPg){
assert( pPg->pgno==1 );
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
pPager = pPg->pPager;
+ sqlite3PagerResetLockTimeout(pPager);
sqlite3PcacheRelease(pPg);
pagerUnlockIfUnused(pPager);
}
@@ -6970,6 +6971,18 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){
return pPager->fd;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+/*
+** Reset the lock timeout for pager.
+*/
+void sqlite3PagerResetLockTimeout(Pager *pPager){
+ if( isOpen(pPager->fd) ){
+ int x = 0;
+ sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
+ }
+}
+#endif
+
/*
** Return the file handle for the journal file (if it exists).
** This will be either the rollback journal or the WAL file.
@@ -7430,6 +7443,7 @@ int sqlite3PagerCheckpoint(
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
+ sqlite3PagerResetLockTimeout(pPager);
}
return rc;
}
diff --git a/src/pager.h b/src/pager.h
index 48bc80df1..730e366fb 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -212,6 +212,11 @@ int sqlite3PagerIsMemdb(Pager*);
void sqlite3PagerCacheStat(Pager *, int, int, int *);
void sqlite3PagerClearCache(Pager*);
int sqlite3SectorSize(sqlite3_file *);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+void sqlite3PagerResetLockTimeout(Pager *pPager);
+#else
+# define sqlite3PagerResetLockTimeout(X)
+#endif
/* Functions used to truncate the database file. */
void sqlite3PagerTruncateImage(Pager*,Pgno);