/ Check-in [a593d574]
Login

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

Overview
Comment:Additional changes in the pager and os interface layers to fix problems that might be contributing to recently observed database corruption. (CVS 3549)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a593d5743eab12c0f93a7bc436f0d69dfab0c387
User & Date: drh 2007-01-03 23:36:22
Context
2007-01-03
23:37
Clean up memory leaks and uninitialized variables detected by valgrind. Identify all tests where we deliberately derefence freed memory by adding a "-misuse" tag. (CVS 3550) check-in: 70a86270 user: drh tags: trunk
23:36
Additional changes in the pager and os interface layers to fix problems that might be contributing to recently observed database corruption. (CVS 3549) check-in: a593d574 user: drh tags: trunk
15:34
Make sure that the database size cache in the pager is invalidated whenever the database is unlocked. A stale value in the database size cache can result in database corruption on a heavily loaded system running autovacuum. (CVS 3548) check-in: 6806b9ec user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  1028   1028     SEEK(0);
  1029   1029     SimulateIOError( got = -1 );
  1030   1030     if( got==amt ){
  1031   1031       return SQLITE_OK;
  1032   1032     }else if( got<0 ){
  1033   1033       return SQLITE_IOERR_READ;
  1034   1034     }else{
         1035  +    memset(&((char*)pBuf)[got], 0, amt-got);
  1035   1036       return SQLITE_IOERR_SHORT_READ;
  1036   1037     }
  1037   1038   }
  1038   1039   
  1039   1040   /*
  1040   1041   ** Seek to the offset in id->offset then read cnt bytes into pBuf.
  1041   1042   ** Return the number of bytes actually read.  Update the offset.

Changes to src/os_win.c.

  1006   1006       got = -1;
  1007   1007     }
  1008   1008     if( got==(DWORD)amt ){
  1009   1009       return SQLITE_OK;
  1010   1010     }else if( got<0 ){
  1011   1011       return SQLITE_IOERR_READ;
  1012   1012     }else{
         1013  +    memset(&((char*)pBuf)[got], 0, amt-got);
  1013   1014       return SQLITE_IOERR_SHORT_READ;
  1014   1015     }
  1015   1016   }
  1016   1017   
  1017   1018   /*
  1018   1019   ** Write data from a buffer into a file.  Return SQLITE_OK on success
  1019   1020   ** or some other error code on failure.

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.279 2007/01/03 15:34:30 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.280 2007/01/03 23:36:22 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include "os.h"
    26     26   #include "pager.h"
    27     27   #include <assert.h>
    28     28   #include <string.h>
................................................................................
   859    859   */
   860    860   static void pager_unlock(Pager *pPager){
   861    861     if( !MEMDB ){
   862    862       sqlite3OsUnlock(pPager->fd, NO_LOCK);
   863    863       pPager->dbSize = -1;
   864    864     }
   865    865     pPager->state = PAGER_UNLOCK;
          866  +  assert( pPager->pAll==0 );
   866    867   }
   867    868   
   868    869   
   869    870   /*
   870    871   ** Unlock the database and clear the in-memory cache.  This routine
   871    872   ** sets the state of the pager back to what it was when it was first
   872    873   ** opened.  Any outstanding pages are invalidated and subsequent attempts
................................................................................
   888    889     pPager->nPage = 0;
   889    890     pPager->aHash = 0;
   890    891     if( pPager->state>=PAGER_RESERVED ){
   891    892       sqlite3pager_rollback(pPager);
   892    893     }
   893    894     pager_unlock(pPager);
   894    895     pPager->nRef = 0;
   895         -  assert( pPager->journalOpen==0 );
          896  +  assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
   896    897   }
   897    898   
   898    899   /*
   899    900   ** When this routine is called, the pager has the journal file open and
   900    901   ** a RESERVED or EXCLUSIVE lock on the database.  This routine releases
   901    902   ** the database lock and acquires a SHARED lock in its place.  The journal
   902    903   ** file is deleted and closed.
................................................................................
  2059   2060   **
  2060   2061   ** This function always succeeds. If a transaction is active an attempt
  2061   2062   ** is made to roll it back. If an error occurs during the rollback 
  2062   2063   ** a hot journal may be left in the filesystem but no error is returned
  2063   2064   ** to the caller.
  2064   2065   */
  2065   2066   int sqlite3pager_close(Pager *pPager){
  2066         -  PgHdr *pPg, *pNext;
  2067   2067   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  2068   2068     /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
  2069   2069     ** malloc() must have already been made by this thread before it gets
  2070   2070     ** to this point. This means the ThreadData must have been allocated already
  2071   2071     ** so that ThreadData.nAlloc can be set.
  2072   2072     */
  2073   2073     ThreadData *pTsd = sqlite3ThreadData();
  2074   2074     assert( pPager );
  2075   2075     assert( pTsd && pTsd->nAlloc );
  2076   2076   #endif
  2077   2077   
  2078         -  switch( pPager->state ){
  2079         -    case PAGER_RESERVED:
  2080         -    case PAGER_SYNCED: 
  2081         -    case PAGER_EXCLUSIVE: {
  2082         -      /* We ignore any IO errors that occur during the rollback
  2083         -      ** operation. So disable IO error simulation so that testing
  2084         -      ** works more easily.
  2085         -      */
  2086         -      disable_simulated_io_errors();
  2087         -      sqlite3pager_rollback(pPager);
  2088         -      enable_simulated_io_errors();
  2089         -      pager_unlock(pPager);
  2090         -      assert( pPager->errCode || pPager->journalOpen==0 );
  2091         -      break;
  2092         -    }
  2093         -    case PAGER_SHARED: {
  2094         -      pager_unlock(pPager);
  2095         -      break;
  2096         -    }
  2097         -    default: {
  2098         -      /* Do nothing */
  2099         -      break;
  2100         -    }
  2101         -  }
  2102         -  for(pPg=pPager->pAll; pPg; pPg=pNext){
  2103         -#ifndef NDEBUG
  2104         -    if( MEMDB ){
  2105         -      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
  2106         -      assert( !pPg->alwaysRollback );
  2107         -      assert( !pHist->pOrig );
  2108         -      assert( !pHist->pStmt );
  2109         -    }
  2110         -#endif
  2111         -    pNext = pPg->pNextAll;
  2112         -    sqliteFree(pPg);
  2113         -  }
         2078  +  disable_simulated_io_errors();
         2079  +  pager_reset(pPager);
         2080  +  enable_simulated_io_errors();
  2114   2081     TRACE2("CLOSE %d\n", PAGERID(pPager));
  2115   2082     assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
  2116   2083     if( pPager->journalOpen ){
  2117   2084       sqlite3OsClose(&pPager->jfd);
  2118   2085     }
  2119   2086     sqliteFree(pPager->aInJournal);
  2120   2087     if( pPager->stmtOpen ){
................................................................................
  2985   2952       /* If this was a malloc() failure, then we will not be closing the pager
  2986   2953       ** file. So delete any journal file we may have just created. Otherwise,
  2987   2954       ** the system will get confused, we have a read-lock on the file and a
  2988   2955       ** mysterious journal has appeared in the filesystem.
  2989   2956       */
  2990   2957       sqlite3OsDelete(pPager->zJournal);
  2991   2958     }else{
  2992         -    pager_unlock(pPager);
         2959  +    pager_reset(pPager);
  2993   2960     }
  2994   2961     return rc;
  2995   2962   }
  2996   2963   
  2997   2964   /*
  2998   2965   ** Acquire a write-lock on the database.  The lock is removed when
  2999   2966   ** the any of the following happen: