From 9c105bb990007c678ca28e63b764f8d0b557d5f9 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 2 Oct 2004 20:38:28 +0000 Subject: [PATCH] Fixes to the OsUnlock() interface. Correctly leave a SHARED lock behind when requested. Honor the error code that OsUnlock() returns. Ticket #913 and #938. (CVS 1997) FossilOrigin-Name: c4697503d0ad080290b91e96dfc9a1a63f2df7e6 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/os_unix.c | 22 +++++++++++++++------- src/os_win.c | 38 +++++++++++++++++++++----------------- src/pager.c | 27 +++++++++++++++------------ 5 files changed, 61 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index f35deab1d6..4d683c9e46 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C make\sdiskfull\stest\swork\son\sWindows;\ssee\scheck-in\s(1994)\s(CVS\s1996) -D 2004-10-01T18:21:43 +C Fixes\sto\sthe\sOsUnlock()\sinterface.\s\sCorrectly\sleave\sa\sSHARED\slock\sbehind\nwhen\srequested.\s\sHonor\sthe\serror\scode\sthat\sOsUnlock()\sreturns.\nTicket\s#913\sand\s#938.\s(CVS\s1997) +D 2004-10-02T20:38:28 F Makefile.in abdeb5bd9d017822691884935c320037c33f6ee6 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -47,11 +47,11 @@ F src/os_mac.c 7367dab0c44ab0b2c4337e73ac6f6f97f171c2cb F src/os_mac.h 608fdf39eafa1ce25fc8cb223b8b0a073341d4da F src/os_test.c d9a21852d170f20adeae6f224d1beba2cb5af8aa F src/os_test.h 6a26a4978492e4bbdbf385554958418ff02db162 -F src/os_unix.c ca7891d1f84994559899ced37b45541a68028282 +F src/os_unix.c 5c1f362846afec4232c2291b9f1564f0487e91f4 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 -F src/os_win.c 2b4b103d978daa5efb6ccb11703976429e0aad84 +F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 39e0ad16ffb94fecf3dc9fd73bccf3e7445f0e17 +F src/pager.c d3688828d314135ef0cd87b4d892805136c4168f F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 F src/parse.y 968231351dd13ef6ee544336295db54708c22faf F src/pragma.c 45978cc82fdf91f00d024a8e875c2b679fbce488 @@ -248,7 +248,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 44e56f0bba61245d342d6e75510d6c35785efd49 -R a61ce3be739beac85c756189a58b0ec2 -U dougcurrie -Z 4de85fdbce139eac43154165436a4c4e +P 4493e287809874fabeddf5ca9045065a30790f2f +R ebf4aac4c1a61ea57872e563bbdb1393 +U drh +Z 44aded0ba9c92340348fe0ad36d9356d diff --git a/manifest.uuid b/manifest.uuid index 8d106700a1..1525b3ca03 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4493e287809874fabeddf5ca9045065a30790f2f \ No newline at end of file +c4697503d0ad080290b91e96dfc9a1a63f2df7e6 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index a5be702f28..88d35f9ce8 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1021,11 +1021,14 @@ end_lock: ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** -** It is not possible for this routine to fail. +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK, this routine +** might return SQLITE_IOERR instead of SQLITE_OK. */ int sqlite3OsUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; + int rc = SQLITE_OK; assert( id->isOpen ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, @@ -1040,11 +1043,16 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ assert( pLock->cnt!=0 ); if( id->locktype>SHARED_LOCK ){ assert( pLock->locktype==id->locktype ); - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = SHARED_FIRST; - lock.l_len = SHARED_SIZE; - fcntl(id->h, F_SETLK, &lock); + 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(id->h, F_SETLK, &lock)!=0 ){ + /* This should never happen */ + rc = SQLITE_IOERR; + } + } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; @@ -1087,7 +1095,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ } sqlite3OsLeaveMutex(); id->locktype = locktype; - return SQLITE_OK; + return rc; } /* diff --git a/src/os_win.c b/src/os_win.c index c79ae62857..f6e3e3ea83 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -375,20 +375,23 @@ static int isNT(void){ } /* -** Acquire a reader lock on the range of bytes from iByte...iByte+nByte-1. +** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ -static int getReadLock(HANDLE h, unsigned int iByte, unsigned int nByte){ +static int getReadLock(OsFile *id){ int res; if( isNT() ){ OVERLAPPED ovlp; - ovlp.Offset = iByte; + ovlp.Offset = SHARED_FIRST; ovlp.OffsetHigh = 0; ovlp.hEvent = 0; - res = LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, nByte, 0, &ovlp); + res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp); }else{ - res = LockFile(h, iByte, 0, nByte, 0); + int lk; + sqlite3Randomness(sizeof(lk), &lk); + id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); } return res; } @@ -479,14 +482,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ */ if( locktype==SHARED_LOCK && res ){ assert( id->locktype==NO_LOCK ); - if( isNT() ){ - res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE); - }else{ - int lk; - sqlite3Randomness(sizeof(lk), &lk); - id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); - res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); - } + res = getReadLock(id); if( res ){ newLocktype = SHARED_LOCK; } @@ -573,10 +569,13 @@ int sqlite3OsCheckReservedLock(OsFile *id){ ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** -** It is not possible for this routine to fail. +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine +** might return SQLITE_IOERR; */ int sqlite3OsUnlock(OsFile *id, int locktype){ - int rc, type; + int type; + int rc = SQLITE_OK; assert( id->isOpen ); assert( locktype<=SHARED_LOCK ); TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, @@ -584,18 +583,23 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ type = id->locktype; if( type>=EXCLUSIVE_LOCK ){ UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !getReadLock(id) ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + rc = SQLITE_IOERR; + } } if( type>=RESERVED_LOCK ){ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); } - if( locktype==NO_LOCK && type>=SHARED_LOCK && type=SHARED_LOCK ){ unlockReadLock(id); } if( type>=PENDING_LOCK ){ UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); } id->locktype = locktype; - return SQLITE_OK; + return rc; } /* diff --git a/src/pager.c b/src/pager.c index d62c490d9a..8b20c16c52 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.165 2004/10/01 02:00:31 drh Exp $ +** @(#) $Id: pager.c,v 1.166 2004/10/02 20:38:28 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -755,6 +755,7 @@ static void pager_reset(Pager *pPager){ */ static int pager_unwritelock(Pager *pPager){ PgHdr *pPg; + int rc; assert( !pPager->memDb ); if( pPager->statedirtyCache==0 || pPager->useJournal==0 ); } - sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); + rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; - return SQLITE_OK; + return rc; } /* @@ -2342,20 +2343,15 @@ static int pager_open_journal(Pager *pPager){ sqlite3pager_pagecount(pPager); pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInJournal==0 ){ - sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); - pPager->state = PAGER_SHARED; - return SQLITE_NOMEM; + rc = SQLITE_NOMEM; + goto failed_to_open_journal; } rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ - sqliteFree(pPager->aInJournal); - pPager->aInJournal = 0; - sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); - pPager->state = PAGER_SHARED; - return rc; + goto failed_to_open_journal; } sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); pPager->journalOpen = 1; @@ -2380,7 +2376,14 @@ static int pager_open_journal(Pager *pPager){ rc = SQLITE_FULL; } } - return rc; + return rc; + +failed_to_open_journal: + sqliteFree(pPager->aInJournal); + pPager->aInJournal = 0; + sqlite3OsUnlock(&pPager->fd, NO_LOCK); + pPager->state = PAGER_UNLOCK; + return rc; } /*