1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Modifications to the way blocking locks are used in SQLITE_ENABLE_SETLK_TIMEOUT builds so that multiple processes or threads may not deadlock when operating on a single database.

FossilOrigin-Name: c516027d5fd876b7d0bf566435667d554db29ded30ad6fc1165caa4a93d015a0
This commit is contained in:
dan
2020-03-27 17:23:17 +00:00
parent 95b395901a
commit 97ccc1bd11
6 changed files with 79 additions and 18 deletions

View File

@@ -1140,6 +1140,11 @@ static int walIndexRecover(Wal *pWal){
u32 aFrameCksum[2] = {0, 0};
int iLock; /* Lock offset to lock for checkpoint */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int tmout = 0;
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
#endif
/* Obtain an exclusive lock on all byte in the locking range not already
** locked by the caller. The caller is guaranteed to have locked the
** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
@@ -2758,6 +2763,9 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int tmout = 0;
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
int bChanged = 0;
@@ -2767,6 +2775,12 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
}
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/* Disable blocking locks. They are not useful when trying to open a
** read-transaction, and blocking may cause deadlock anyway. */
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
#endif
do{
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
}while( rc==WAL_RETRY );
@@ -2775,6 +2789,16 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
testcase( rc==SQLITE_PROTOCOL );
testcase( rc==SQLITE_OK );
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/* If they were disabled earlier and the read-transaction has been
** successfully opened, re-enable blocking locks. This is because the
** connection may attempt to upgrade to a write-transaction, which does
** benefit from using blocking locks. */
if( rc==SQLITE_OK ){
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
}
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
if( rc==SQLITE_OK ){
if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){