mirror of https://github.com/sqlite/sqlite
Revise and vastly simplify the Win32 SHM file locking semantics, allowing all new tests to pass.
FossilOrigin-Name: d0997b0f5bc9a9869684e39a17a01c430d6383c8b31d6c00ea17a5eac15bc6f0
This commit is contained in:
parent
95a05aae67
commit
7b7f224c62
12
manifest
12
manifest
|
@ -1,5 +1,5 @@
|
|||
C Add\san\sassert()\sin\sthe\sWin32\sVFS.
|
||||
D 2017-11-09T20:37:37.876
|
||||
C Revise\sand\svastly\ssimplify\sthe\sWin32\sSHM\sfile\slocking\ssemantics,\sallowing\sall\snew\stests\sto\spass.
|
||||
D 2017-11-09T22:23:50.758
|
||||
F Makefile.in 5bae3f2f3d42f2ad52b141562d74872c97ac0fca6c54953c91bb150a0e6427a8
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 3a5cb477ec3ce5274663b693164e349db63348667cd45bad78cc13d580b691e2
|
||||
|
@ -448,7 +448,7 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
|||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c e87cef0bb894b94d96ee3af210be669549d111c580817d14818101b992640767
|
||||
F src/os_win.c 64bc61821f75b37ca213da93aef84557c8730be6e0ca93943223b5e57fe6e5a3
|
||||
F src/os_win.c b40d4f98562048b1d084b71bb08367903b937424427ee7b866902dca7b79cb88
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903
|
||||
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
|
||||
|
@ -1669,7 +1669,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P ff630b66714b20c09888ead0a45f344d63e0d9a5208867d6266e74f79187076c
|
||||
R 9f94324b020c3efbc23aa89a0c6b1ac2
|
||||
P 22e58330461736ca22d6f4d7eab897a3597de2e7434a6f4a474f0f0d7f964281
|
||||
R 0c5d22f8af57ea73c927075712f52c29
|
||||
U mistachkin
|
||||
Z b9496fb62e9a99521b89e7f9003a99d8
|
||||
Z e19a1ec884226a6dec0cb1fab52ceb52
|
||||
|
|
|
@ -1 +1 @@
|
|||
22e58330461736ca22d6f4d7eab897a3597de2e7434a6f4a474f0f0d7f964281
|
||||
d0997b0f5bc9a9869684e39a17a01c430d6383c8b31d6c00ea17a5eac15bc6f0
|
128
src/os_win.c
128
src/os_win.c
|
@ -2098,27 +2098,6 @@ static int winLogErrorAtLine(
|
|||
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
|
||||
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
|
||||
|
||||
/*
|
||||
** The "winIsLockConflict" macro is used to determine if a particular I/O
|
||||
** error code is due to a file locking conflict. It must accept the error
|
||||
** code DWORD as its only argument.
|
||||
*/
|
||||
#if !defined(winIsLockConflict)
|
||||
#define winIsLockConflict(a) (((a)==NO_ERROR) || \
|
||||
((a)==ERROR_LOCK_VIOLATION) || \
|
||||
((a)==ERROR_IO_PENDING))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The "winIsLockMissing" macro is used to determine if a particular I/O
|
||||
** error code is due to being unable to obtain a file lock because all or
|
||||
** part of the range requested within the file is missing. It must accept
|
||||
** the error code DWORD as its only argument.
|
||||
*/
|
||||
#if !defined(winIsLockMissing)
|
||||
#define winIsLockMissing(a) (((a)==ERROR_HANDLE_EOF))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
|
||||
** error code obtained via GetLastError() is eligible to be retried. It
|
||||
|
@ -3844,65 +3823,6 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Query the status of the DMS lock for the specified file. Returns
|
||||
** SQLITE_OK upon success. Upon success, the integer pointed to by
|
||||
** the pLockType argument will be set to the lock type held by the
|
||||
** other process, as follows:
|
||||
**
|
||||
** WINSHM_UNLCK -- No locks are held on the DMS.
|
||||
** WINSHM_RDLCK -- A SHARED lock is held on the DMS.
|
||||
** WINSHM_WRLCK -- An EXCLUSIVE lock is held on the DMS.
|
||||
*/
|
||||
static int winGetShmDmsLockType(
|
||||
winFile *pFile, /* File handle object */
|
||||
int bReadOnly, /* Non-zero if the SHM was opened read-only */
|
||||
int *pLockType /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
|
||||
){
|
||||
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
OVERLAPPED overlapped; /* The offset for ReadFile/WriteFile. */
|
||||
#endif
|
||||
LPVOID pOverlapped = 0;
|
||||
sqlite3_int64 offset = WIN_SHM_DMS;
|
||||
BYTE notUsed1 = 0;
|
||||
DWORD notUsed2 = 0;
|
||||
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
if( winSeekFile(pFile, offset) ){
|
||||
return SQLITE_IOERR_SEEK;
|
||||
}
|
||||
#else
|
||||
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
||||
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
||||
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
||||
pOverlapped = &overlapped;
|
||||
#endif
|
||||
if( bReadOnly ||
|
||||
!osWriteFile(pFile->h, ¬Used1, 1, ¬Used2, pOverlapped) ){
|
||||
DWORD lastErrno = bReadOnly ? NO_ERROR : osGetLastError();
|
||||
if( !osReadFile(pFile->h, ¬Used1, 1, ¬Used2, pOverlapped) ){
|
||||
lastErrno = osGetLastError();
|
||||
if( winIsLockConflict(lastErrno) ){
|
||||
if( pLockType ) *pLockType = WINSHM_WRLCK;
|
||||
}else if( winIsLockMissing(lastErrno) ){
|
||||
assert( bReadOnly );
|
||||
if( pLockType ) *pLockType = WINSHM_UNLCK;
|
||||
}else{
|
||||
return SQLITE_IOERR_READ;
|
||||
}
|
||||
}else{
|
||||
if( winIsLockConflict(lastErrno) ){
|
||||
if( pLockType ) *pLockType = WINSHM_RDLCK;
|
||||
}else{
|
||||
return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( pLockType ) *pLockType = WINSHM_UNLCK;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
|
||||
** take it now. Return SQLITE_OK if successful, or an SQLite error
|
||||
|
@ -3913,53 +3833,21 @@ static int winGetShmDmsLockType(
|
|||
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
|
||||
*/
|
||||
static int winLockSharedMemory(winShmNode *pShmNode){
|
||||
int lockType;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* Use ReadFile/WriteFile to determine the locks other processes are
|
||||
** holding on the DMS byte. If it indicates that another process is
|
||||
** holding a SHARED lock, then this process may also take a SHARED
|
||||
** lock and proceed with opening the *-shm file.
|
||||
**
|
||||
** Or, if no other process is holding any lock, then this process
|
||||
** is the first to open it. In this case take an EXCLUSIVE lock on the
|
||||
** DMS byte and truncate the *-shm file to zero bytes in size. Then
|
||||
** downgrade to a SHARED lock on the DMS byte.
|
||||
**
|
||||
** If another process is holding an EXCLUSIVE lock on the DMS byte,
|
||||
** return SQLITE_BUSY to the caller (it will try again). An earlier
|
||||
** version of this code attempted the SHARED lock at this point. But
|
||||
** this introduced a subtle race condition: if the process holding
|
||||
** EXCLUSIVE failed just before truncating the *-shm file, then this
|
||||
** process might open and use the *-shm file without truncating it.
|
||||
** And if the *-shm file has been corrupted by a power failure or
|
||||
** system crash, the database itself may also become corrupt. */
|
||||
if( winGetShmDmsLockType(&pShmNode->hFile, pShmNode->isReadonly,
|
||||
&lockType)!=SQLITE_OK ){
|
||||
rc = SQLITE_IOERR_LOCK;
|
||||
}else if( lockType==WINSHM_UNLCK ){
|
||||
int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pShmNode->isReadonly ){
|
||||
pShmNode->isUnlocked = 1;
|
||||
rc = SQLITE_READONLY_CANTINIT;
|
||||
}else{
|
||||
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
|
||||
if( rc==SQLITE_OK && winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
|
||||
rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
|
||||
return SQLITE_READONLY_CANTINIT;
|
||||
}else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
|
||||
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
|
||||
"winLockSharedMemory", pShmNode->zFilename);
|
||||
}
|
||||
}
|
||||
}else if( lockType==WINSHM_WRLCK ){
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( lockType==WINSHM_UNLCK || lockType==WINSHM_RDLCK );
|
||||
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
||||
return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue