From: mistachkin Date: Thu, 9 Nov 2017 22:23:50 +0000 (+0000) Subject: Revise and vastly simplify the Win32 SHM file locking semantics, allowing all new... X-Git-Tag: version-3.22.0~199^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7b7f224c6242f032e2e1d84e4aeb78ede1cbcae1;p=thirdparty%2Fsqlite.git Revise and vastly simplify the Win32 SHM file locking semantics, allowing all new tests to pass. FossilOrigin-Name: d0997b0f5bc9a9869684e39a17a01c430d6383c8b31d6c00ea17a5eac15bc6f0 --- diff --git a/manifest b/manifest index 68233db669..bf3dc40e6b 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index da346528d8..2503e60869 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22e58330461736ca22d6f4d7eab897a3597de2e7434a6f4a474f0f0d7f964281 \ No newline at end of file +d0997b0f5bc9a9869684e39a17a01c430d6383c8b31d6c00ea17a5eac15bc6f0 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index aff48e25e9..975df6154b 100644 --- a/src/os_win.c +++ b/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); } /*