/ Check-in [a718e663]
Login

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

Overview
Comment:Avoid a race condition in the sqlite3_release_memory() logic within pager.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.5.9
Files: files | file ages | folders
SHA1: a718e6634795a48b5dd5c08833ab561e6381a62d
User & Date: drh 2010-01-30 19:17:07
Context
2010-01-30
22:28
Always hold the MEM2 mutex when initially marking a pager as in use by its database connection. check-in: 622c1717 user: drh tags: branch-3.5.9
19:17
Avoid a race condition in the sqlite3_release_memory() logic within pager.c. check-in: a718e663 user: drh tags: branch-3.5.9
19:00
Remove all cache pages from the LRU list prior to removing the pager from the pager list when closing a pager. check-in: 9d13acc4 user: drh tags: branch-3.5.9
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
....
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
  */
  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
     pPager->iInUseMM = 1;
  }

  while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
    PgHdr *pPg;
    PgHdr *pRecycled;
 
    /* Try to find a page to recycle that does not require a sync(). If
    ** this is not possible, find one that does require a sync().
    */
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    pPg = sqlite3LruPageList.pFirstSynced;
    while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
................................................................................
    /* If pPg==0, then the block above has failed to find a page to
    ** recycle. In this case return early - no further memory will
    ** be released.
    */
    if( !pPg ) break;

    pPager = pPg->pPager;
    assert(!pPg->needSync || pPg==pPager->lru.pFirst);
    assert(pPg->needSync || pPg==pPager->lru.pFirstSynced);
  
    savedBusy = pPager->pBusyHandler;
    pPager->pBusyHandler = 0;
    rc = pager_recycle(pPager, &pRecycled);
    pPager->pBusyHandler = savedBusy;
    assert(pRecycled==pPg || rc!=SQLITE_OK);
    if( rc==SQLITE_OK ){
      /* We've found a page to free. At this point the page has been 
      ** removed from the page hash-table, free-list and synced-list 
      ** (pFirstSynced). It is still in the all pages (pAll) list. 
      ** Remove it from this list before freeing.
      **
      ** Todo: Check the Pager.pStmt list to make sure this is Ok. It 







<







 







<
<
<


|

<







3290
3291
3292
3293
3294
3295
3296

3297
3298
3299
3300
3301
3302
3303
....
3314
3315
3316
3317
3318
3319
3320



3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
  */
  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
     pPager->iInUseMM = 1;
  }

  while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
    PgHdr *pPg;

 
    /* Try to find a page to recycle that does not require a sync(). If
    ** this is not possible, find one that does require a sync().
    */
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    pPg = sqlite3LruPageList.pFirstSynced;
    while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
................................................................................
    /* If pPg==0, then the block above has failed to find a page to
    ** recycle. In this case return early - no further memory will
    ** be released.
    */
    if( !pPg ) break;

    pPager = pPg->pPager;



    savedBusy = pPager->pBusyHandler;
    pPager->pBusyHandler = 0;
    rc = pager_recycle(pPager, &pPg);
    pPager->pBusyHandler = savedBusy;

    if( rc==SQLITE_OK ){
      /* We've found a page to free. At this point the page has been 
      ** removed from the page hash-table, free-list and synced-list 
      ** (pFirstSynced). It is still in the all pages (pAll) list. 
      ** Remove it from this list before freeing.
      **
      ** Todo: Check the Pager.pStmt list to make sure this is Ok. It