/ Check-in [e6108047]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In wal mode, if a "BEGIN EXCLUSIVE" command (or any other command that upgrades from no transaction directly to a write transaction) hits an SQLITE_BUSY_SNAPSHOT error, change the error code to SQLITE_BUSY to indicate to the caller that the condition may be transient.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:e6108047cb136119d8ed19af010a669ed9750b4e7f991ccabc9e3d15774eda31
User & Date: dan 2018-07-05 17:16:55
Context
2018-07-05
17:35
Fix the .dump command in the command-line shell so that it does not show extraneous SELECT statements when ".echo on" is enabled. check-in: 11763cac user: drh tags: trunk
17:16
In wal mode, if a "BEGIN EXCLUSIVE" command (or any other command that upgrades from no transaction directly to a write transaction) hits an SQLITE_BUSY_SNAPSHOT error, change the error code to SQLITE_BUSY to indicate to the caller that the condition may be transient. check-in: e6108047 user: dan tags: trunk
17:03
Fix a typo inside an assert() statement introduced by the previous commit. Closed-Leaf check-in: e3357728 user: dan tags: exp-busy-snapshot-fix
2018-07-03
20:17
Test that a race condition can cause a "BEGIN EXCLUSIVE" to return SQLITE_BUSY_SNAPSHOT in wal mode. check-in: 5a12db75 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

3371
3372
3373
3374
3375
3376
3377





3378
3379
3380
3381
3382
3383
3384
....
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
    if( rc==SQLITE_OK && wrflag ){
      if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
        rc = SQLITE_READONLY;
      }else{
        rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
        if( rc==SQLITE_OK ){
          rc = newDatabase(pBt);





        }
      }
    }
  
    if( rc!=SQLITE_OK ){
      unlockBtreeIfUnused(pBt);
    }
................................................................................
        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }


trans_begun:
  if( rc==SQLITE_OK ){
    if( pSchemaVersion ){
      *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
    }
    if( wrflag ){







>
>
>
>
>







 







<







3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
....
3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
    if( rc==SQLITE_OK && wrflag ){
      if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
        rc = SQLITE_READONLY;
      }else{
        rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
        if( rc==SQLITE_OK ){
          rc = newDatabase(pBt);
        }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
          /* if there was no transaction opened when this function was
          ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
          ** code to SQLITE_BUSY. */
          rc = SQLITE_BUSY;
        }
      }
    }
  
    if( rc!=SQLITE_OK ){
      unlockBtreeIfUnused(pBt);
    }
................................................................................
        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }


trans_begun:
  if( rc==SQLITE_OK ){
    if( pSchemaVersion ){
      *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
    }
    if( wrflag ){

Changes to test/walprotocol2.test.

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  }
}
do_catchsql_test 2.2 {
  BEGIN EXCLUSIVE;
} {1 {database is locked}}
do_test 2.3 {
  sqlite3_extended_errcode db
} {SQLITE_BUSY_SNAPSHOT}

#---------------------------------------------------------------
# Same again, but with a busy-handler. This time, following the
# SQLITE_BUSY_SNAPSHOT error the busy-handler is invoked and then the 
# whole thing retried from the beginning. This time it succeeds.
#
proc lock_callback {method filename handle lock} {







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  }
}
do_catchsql_test 2.2 {
  BEGIN EXCLUSIVE;
} {1 {database is locked}}
do_test 2.3 {
  sqlite3_extended_errcode db
} {SQLITE_BUSY}

#---------------------------------------------------------------
# Same again, but with a busy-handler. This time, following the
# SQLITE_BUSY_SNAPSHOT error the busy-handler is invoked and then the 
# whole thing retried from the beginning. This time it succeeds.
#
proc lock_callback {method filename handle lock} {