1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Clarify the purpose of a test for a race-condition in walIndexReadHdr().

FossilOrigin-Name: c041c6a9786bc9ebb82527f7a2c96d255aec927f
This commit is contained in:
dan
2010-06-05 18:34:26 +00:00
parent 493cc590b6
commit eb8cb3a851
3 changed files with 30 additions and 9 deletions

View File

@@ -1745,6 +1745,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** and can be safely ignored.
*/
rc = walLockShared(pWal, WAL_READ_LOCK(0));
sqlite3OsShmBarrier(pWal->pDbFd);
if( rc==SQLITE_OK ){
if( memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
/* It is not safe to allow the reader to continue here if frames
@@ -1817,9 +1818,29 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
if( rc ){
return rc==SQLITE_BUSY ? WAL_RETRY : rc;
}
/* Now that the read-lock has been obtained, check that neither the
** value in the aReadMark[] array or the contents of the wal-index
** header have changed.
**
** It is necessary to check that the wal-index header did not change
** between the time it was read and when the shared-lock was obtained
** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
** that the log file may have been wrapped by a writer, or that frames
** that occur later in the log than pWal->hdr.mxFrame may have been
** copied into the database by a checkpointer. If either of these things
** happened, then reading the database with the current value of
** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
** instead.
**
** This does not guarantee that the copy wal-index header is up to
** date before proceeding. This would not be possible without somehow
** blocking writers. It only guarantees that a damaging checkpoint or
** log-wrap (either of which would require an exclusive lock on
** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
*/
sqlite3OsShmBarrier(pWal->pDbFd);
if( pInfo->aReadMark[mxI]!=mxReadMark
|| pHdr[0].mxFrame!=pWal->hdr.mxFrame
|| (sqlite3OsShmBarrier(pWal->pDbFd), pHdr[1].mxFrame!=pWal->hdr.mxFrame)
|| memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr))
){
walUnlockShared(pWal, WAL_READ_LOCK(mxI));
return WAL_RETRY;