/ Check-in [5b03ba9d]
Login

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

Overview
Comment:Merge the winGetLastError fixes into trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5b03ba9db0d23a8597b45e00ad5892c8065ce1cd
User & Date: drh 2011-12-06 00:47:51
Context
2011-12-06
13:24
Do not reuse temp registers originally allocated to a subroutine within the main body of the program logic, since if the subroutine is called while the reused temp registers are in use, their values will get clobbered. Candidate fix for ticket [3a77c9714e63330] check-in: 092d5331 user: drh tags: trunk
00:47
Merge the winGetLastError fixes into trunk. check-in: 5b03ba9d user: drh tags: trunk
2011-11-29
15:40
Remove unused fields from the Parse object. Documentation and formatting improvements on data structure definitions. check-in: 431556ca user: drh tags: trunk
2011-11-21
00:54
Cleanup the semantics surrounding use of the GetLastError function on Windows. Closed-Leaf check-in: 7e657bbb user: mistachkin tags: winGetLastError
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_win.c.

  1166   1166   static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
  1167   1167   
  1168   1168   /*
  1169   1169   ** If a ReadFile() or WriteFile() error occurs, invoke this routine
  1170   1170   ** to see if it should be retried.  Return TRUE to retry.  Return FALSE
  1171   1171   ** to give up with an error.
  1172   1172   */
  1173         -static int retryIoerr(int *pnRetry){
  1174         -  DWORD e;
         1173  +static int retryIoerr(int *pnRetry, DWORD *pError){
         1174  +  DWORD e = osGetLastError();
  1175   1175     if( *pnRetry>=win32IoerrRetry ){
         1176  +    if( pError ){
         1177  +      *pError = e;
         1178  +    }
  1176   1179       return 0;
  1177   1180     }
  1178         -  e = osGetLastError();
  1179   1181     if( e==ERROR_ACCESS_DENIED ||
  1180   1182         e==ERROR_LOCK_VIOLATION ||
  1181   1183         e==ERROR_SHARING_VIOLATION ){
  1182   1184       osSleep(win32IoerrRetryDelay*(1+*pnRetry));
  1183   1185       ++*pnRetry;
  1184   1186       return 1;
  1185   1187     }
         1188  +  if( pError ){
         1189  +    *pError = e;
         1190  +  }
  1186   1191     return 0;
  1187   1192   }
  1188   1193   
  1189   1194   /*
  1190   1195   ** Log a I/O error retry episode.
  1191   1196   */
  1192   1197   static void logIoerr(int nRetry){
................................................................................
  1535   1540   ** argument to offset iOffset within the file. If successful, return 0. 
  1536   1541   ** Otherwise, set pFile->lastErrno and return non-zero.
  1537   1542   */
  1538   1543   static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
  1539   1544     LONG upperBits;                 /* Most sig. 32 bits of new offset */
  1540   1545     LONG lowerBits;                 /* Least sig. 32 bits of new offset */
  1541   1546     DWORD dwRet;                    /* Value returned by SetFilePointer() */
         1547  +  DWORD lastErrno;                /* Value returned by GetLastError() */
  1542   1548   
  1543   1549     upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
  1544   1550     lowerBits = (LONG)(iOffset & 0xffffffff);
  1545   1551   
  1546   1552     /* API oddity: If successful, SetFilePointer() returns a dword 
  1547   1553     ** containing the lower 32-bits of the new file-offset. Or, if it fails,
  1548   1554     ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
  1549   1555     ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
  1550   1556     ** whether an error has actually occured, it is also necessary to call 
  1551   1557     ** GetLastError().
  1552   1558     */
  1553   1559     dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
  1554         -  if( (dwRet==INVALID_SET_FILE_POINTER && osGetLastError()!=NO_ERROR) ){
  1555         -    pFile->lastErrno = osGetLastError();
         1560  +
         1561  +  if( (dwRet==INVALID_SET_FILE_POINTER
         1562  +      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
         1563  +    pFile->lastErrno = lastErrno;
  1556   1564       winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
  1557   1565                "seekWinFile", pFile->zPath);
  1558   1566       return 1;
  1559   1567     }
  1560   1568   
  1561   1569     return 0;
  1562   1570   }
................................................................................
  1624   1632     SimulateIOError(return SQLITE_IOERR_READ);
  1625   1633     OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
  1626   1634   
  1627   1635     if( seekWinFile(pFile, offset) ){
  1628   1636       return SQLITE_FULL;
  1629   1637     }
  1630   1638     while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
  1631         -    if( retryIoerr(&nRetry) ) continue;
  1632         -    pFile->lastErrno = osGetLastError();
         1639  +    DWORD lastErrno;
         1640  +    if( retryIoerr(&nRetry, &lastErrno) ) continue;
         1641  +    pFile->lastErrno = lastErrno;
  1633   1642       return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
  1634   1643                "winRead", pFile->zPath);
  1635   1644     }
  1636   1645     logIoerr(nRetry);
  1637   1646     if( nRead<(DWORD)amt ){
  1638   1647       /* Unread parts of the buffer must be zero-filled */
  1639   1648       memset(&((char*)pBuf)[nRead], 0, amt-nRead);
................................................................................
  1665   1674     OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
  1666   1675   
  1667   1676     rc = seekWinFile(pFile, offset);
  1668   1677     if( rc==0 ){
  1669   1678       u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
  1670   1679       int nRem = amt;               /* Number of bytes yet to be written */
  1671   1680       DWORD nWrite;                 /* Bytes written by each WriteFile() call */
         1681  +    DWORD lastErrno = NO_ERROR;   /* Value returned by GetLastError() */
  1672   1682   
  1673   1683       while( nRem>0 ){
  1674   1684         if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
  1675         -        if( retryIoerr(&nRetry) ) continue;
         1685  +        if( retryIoerr(&nRetry, &lastErrno) ) continue;
  1676   1686           break;
  1677   1687         }
  1678   1688         if( nWrite<=0 ) break;
  1679   1689         aRem += nWrite;
  1680   1690         nRem -= nWrite;
  1681   1691       }
  1682   1692       if( nRem>0 ){
  1683         -      pFile->lastErrno = osGetLastError();
         1693  +      pFile->lastErrno = lastErrno;
  1684   1694         rc = 1;
  1685   1695       }
  1686   1696     }
  1687   1697   
  1688   1698     if( rc ){
  1689   1699       if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
  1690   1700          || ( pFile->lastErrno==ERROR_DISK_FULL )){
................................................................................
  1806   1816   /*
  1807   1817   ** Determine the current size of a file in bytes
  1808   1818   */
  1809   1819   static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
  1810   1820     DWORD upperBits;
  1811   1821     DWORD lowerBits;
  1812   1822     winFile *pFile = (winFile*)id;
  1813         -  DWORD error;
         1823  +  DWORD lastErrno;
  1814   1824   
  1815   1825     assert( id!=0 );
  1816   1826     SimulateIOError(return SQLITE_IOERR_FSTAT);
  1817   1827     lowerBits = osGetFileSize(pFile->h, &upperBits);
  1818   1828     if(   (lowerBits == INVALID_FILE_SIZE)
  1819         -     && ((error = osGetLastError()) != NO_ERROR) )
         1829  +     && ((lastErrno = osGetLastError())!=NO_ERROR) )
  1820   1830     {
  1821         -    pFile->lastErrno = error;
         1831  +    pFile->lastErrno = lastErrno;
  1822   1832       return winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
  1823   1833                "winFileSize", pFile->zPath);
  1824   1834     }
  1825   1835     *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
  1826   1836     return SQLITE_OK;
  1827   1837   }
  1828   1838   
................................................................................
  1865   1875   }
  1866   1876   
  1867   1877   /*
  1868   1878   ** Undo a readlock
  1869   1879   */
  1870   1880   static int unlockReadLock(winFile *pFile){
  1871   1881     int res;
         1882  +  DWORD lastErrno;
  1872   1883     if( isNT() ){
  1873   1884       res = osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  1874   1885   /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
  1875   1886   */
  1876   1887   #if SQLITE_OS_WINCE==0
  1877   1888     }else{
  1878   1889       res = osUnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
  1879   1890   #endif
  1880   1891     }
  1881         -  if( res==0 && osGetLastError()!=ERROR_NOT_LOCKED ){
  1882         -    pFile->lastErrno = osGetLastError();
         1892  +  if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
         1893  +    pFile->lastErrno = lastErrno;
  1883   1894       winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
  1884   1895                "unlockReadLock", pFile->zPath);
  1885   1896     }
  1886   1897     return res;
  1887   1898   }
  1888   1899   
  1889   1900   /*
................................................................................
  1914   1925   */
  1915   1926   static int winLock(sqlite3_file *id, int locktype){
  1916   1927     int rc = SQLITE_OK;    /* Return code from subroutines */
  1917   1928     int res = 1;           /* Result of a Windows lock call */
  1918   1929     int newLocktype;       /* Set pFile->locktype to this value before exiting */
  1919   1930     int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
  1920   1931     winFile *pFile = (winFile*)id;
  1921         -  DWORD error = NO_ERROR;
         1932  +  DWORD lastErrno = NO_ERROR;
  1922   1933   
  1923   1934     assert( id!=0 );
  1924   1935     OSTRACE(("LOCK %d %d was %d(%d)\n",
  1925   1936              pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
  1926   1937   
  1927   1938     /* If there is already a lock of this type or more restrictive on the
  1928   1939     ** OsFile, do nothing. Don't use the end_lock: exit path, as
................................................................................
  1956   1967         ** copy this retry logic.  It is a hack intended for Windows only.
  1957   1968         */
  1958   1969         OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
  1959   1970         if( cnt ) osSleep(1);
  1960   1971       }
  1961   1972       gotPendingLock = res;
  1962   1973       if( !res ){
  1963         -      error = osGetLastError();
         1974  +      lastErrno = osGetLastError();
  1964   1975       }
  1965   1976     }
  1966   1977   
  1967   1978     /* Acquire a shared lock
  1968   1979     */
  1969   1980     if( locktype==SHARED_LOCK && res ){
  1970   1981       assert( pFile->locktype==NO_LOCK );
  1971   1982       res = getReadLock(pFile);
  1972   1983       if( res ){
  1973   1984         newLocktype = SHARED_LOCK;
  1974   1985       }else{
  1975         -      error = osGetLastError();
         1986  +      lastErrno = osGetLastError();
  1976   1987       }
  1977   1988     }
  1978   1989   
  1979   1990     /* Acquire a RESERVED lock
  1980   1991     */
  1981   1992     if( locktype==RESERVED_LOCK && res ){
  1982   1993       assert( pFile->locktype==SHARED_LOCK );
  1983   1994       res = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
  1984   1995       if( res ){
  1985   1996         newLocktype = RESERVED_LOCK;
  1986   1997       }else{
  1987         -      error = osGetLastError();
         1998  +      lastErrno = osGetLastError();
  1988   1999       }
  1989   2000     }
  1990   2001   
  1991   2002     /* Acquire a PENDING lock
  1992   2003     */
  1993   2004     if( locktype==EXCLUSIVE_LOCK && res ){
  1994   2005       newLocktype = PENDING_LOCK;
................................................................................
  2001   2012       assert( pFile->locktype>=SHARED_LOCK );
  2002   2013       res = unlockReadLock(pFile);
  2003   2014       OSTRACE(("unreadlock = %d\n", res));
  2004   2015       res = osLockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  2005   2016       if( res ){
  2006   2017         newLocktype = EXCLUSIVE_LOCK;
  2007   2018       }else{
  2008         -      error = osGetLastError();
  2009         -      OSTRACE(("error-code = %d\n", error));
         2019  +      lastErrno = osGetLastError();
         2020  +      OSTRACE(("error-code = %d\n", lastErrno));
  2010   2021         getReadLock(pFile);
  2011   2022       }
  2012   2023     }
  2013   2024   
  2014   2025     /* If we are holding a PENDING lock that ought to be released, then
  2015   2026     ** release it now.
  2016   2027     */
................................................................................
  2022   2033     ** return the appropriate result code.
  2023   2034     */
  2024   2035     if( res ){
  2025   2036       rc = SQLITE_OK;
  2026   2037     }else{
  2027   2038       OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
  2028   2039              locktype, newLocktype));
  2029         -    pFile->lastErrno = error;
         2040  +    pFile->lastErrno = lastErrno;
  2030   2041       rc = SQLITE_BUSY;
  2031   2042     }
  2032   2043     pFile->locktype = (u8)newLocktype;
  2033   2044     return rc;
  2034   2045   }
  2035   2046   
  2036   2047   /*
................................................................................
  2960   2971     sqlite3_vfs *pVfs,        /* Not used */
  2961   2972     const char *zName,        /* Name of the file (UTF-8) */
  2962   2973     sqlite3_file *id,         /* Write the SQLite file handle here */
  2963   2974     int flags,                /* Open mode flags */
  2964   2975     int *pOutFlags            /* Status return flags */
  2965   2976   ){
  2966   2977     HANDLE h;
         2978  +  DWORD lastErrno;
  2967   2979     DWORD dwDesiredAccess;
  2968   2980     DWORD dwShareMode;
  2969   2981     DWORD dwCreationDisposition;
  2970   2982     DWORD dwFlagsAndAttributes = 0;
  2971   2983   #if SQLITE_OS_WINCE
  2972   2984     int isTemp = 0;
  2973   2985   #endif
................................................................................
  3096   3108     if( isNT() ){
  3097   3109       while( (h = osCreateFileW((LPCWSTR)zConverted,
  3098   3110                                 dwDesiredAccess,
  3099   3111                                 dwShareMode, NULL,
  3100   3112                                 dwCreationDisposition,
  3101   3113                                 dwFlagsAndAttributes,
  3102   3114                                 NULL))==INVALID_HANDLE_VALUE &&
  3103         -                              retryIoerr(&cnt) ){}
         3115  +                              retryIoerr(&cnt, &lastErrno) ){}
  3104   3116   /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
  3105   3117   ** Since the ANSI version of these Windows API do not exist for WINCE,
  3106   3118   ** it's important to not reference them for WINCE builds.
  3107   3119   */
  3108   3120   #if SQLITE_OS_WINCE==0
  3109   3121     }else{
  3110   3122       while( (h = osCreateFileA((LPCSTR)zConverted,
  3111   3123                                 dwDesiredAccess,
  3112   3124                                 dwShareMode, NULL,
  3113   3125                                 dwCreationDisposition,
  3114   3126                                 dwFlagsAndAttributes,
  3115   3127                                 NULL))==INVALID_HANDLE_VALUE &&
  3116         -                              retryIoerr(&cnt) ){}
         3128  +                              retryIoerr(&cnt, &lastErrno) ){}
  3117   3129   #endif
  3118   3130     }
  3119   3131   
  3120   3132     logIoerr(cnt);
  3121   3133   
  3122   3134     OSTRACE(("OPEN %d %s 0x%lx %s\n", 
  3123   3135              h, zName, dwDesiredAccess, 
  3124   3136              h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
  3125   3137   
  3126   3138     if( h==INVALID_HANDLE_VALUE ){
  3127         -    pFile->lastErrno = osGetLastError();
         3139  +    pFile->lastErrno = lastErrno;
  3128   3140       winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
  3129   3141       sqlite3_free(zConverted);
  3130   3142       if( isReadWrite && !isExclusive ){
  3131   3143         return winOpen(pVfs, zName, id, 
  3132   3144                ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
  3133   3145       }else{
  3134   3146         return SQLITE_CANTOPEN_BKPT;
................................................................................
  3187   3199   static int winDelete(
  3188   3200     sqlite3_vfs *pVfs,          /* Not used on win32 */
  3189   3201     const char *zFilename,      /* Name of file to delete */
  3190   3202     int syncDir                 /* Not used on win32 */
  3191   3203   ){
  3192   3204     int cnt = 0;
  3193   3205     int rc;
         3206  +  DWORD lastErrno;
  3194   3207     void *zConverted;
  3195   3208     UNUSED_PARAMETER(pVfs);
  3196   3209     UNUSED_PARAMETER(syncDir);
  3197   3210   
  3198   3211     SimulateIOError(return SQLITE_IOERR_DELETE);
  3199   3212     zConverted = convertUtf8Filename(zFilename);
  3200   3213     if( zConverted==0 ){
  3201   3214       return SQLITE_IOERR_NOMEM;
  3202   3215     }
  3203   3216     if( isNT() ){
  3204   3217       rc = 1;
  3205   3218       while( osGetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
  3206         -           (rc = osDeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
         3219  +         (rc = osDeleteFileW(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
  3207   3220       rc = rc ? SQLITE_OK : SQLITE_ERROR;
  3208   3221   /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
  3209   3222   ** Since the ANSI version of these Windows API do not exist for WINCE,
  3210   3223   ** it's important to not reference them for WINCE builds.
  3211   3224   */
  3212   3225   #if SQLITE_OS_WINCE==0
  3213   3226     }else{
  3214   3227       rc = 1;
  3215   3228       while( osGetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
  3216         -           (rc = osDeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
         3229  +         (rc = osDeleteFileA(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
  3217   3230       rc = rc ? SQLITE_OK : SQLITE_ERROR;
  3218   3231   #endif
  3219   3232     }
  3220   3233     if( rc ){
  3221         -    rc = winLogError(SQLITE_IOERR_DELETE, osGetLastError(),
         3234  +    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
  3222   3235                "winDelete", zFilename);
  3223   3236     }else{
  3224   3237       logIoerr(cnt);
  3225   3238     }
  3226   3239     sqlite3_free(zConverted);
  3227   3240     OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
  3228   3241     return rc;
................................................................................
  3235   3248     sqlite3_vfs *pVfs,         /* Not used on win32 */
  3236   3249     const char *zFilename,     /* Name of file to check */
  3237   3250     int flags,                 /* Type of test to make on this file */
  3238   3251     int *pResOut               /* OUT: Result */
  3239   3252   ){
  3240   3253     DWORD attr;
  3241   3254     int rc = 0;
         3255  +  DWORD lastErrno;
  3242   3256     void *zConverted;
  3243   3257     UNUSED_PARAMETER(pVfs);
  3244   3258   
  3245   3259     SimulateIOError( return SQLITE_IOERR_ACCESS; );
  3246   3260     zConverted = convertUtf8Filename(zFilename);
  3247   3261     if( zConverted==0 ){
  3248   3262       return SQLITE_IOERR_NOMEM;
................................................................................
  3249   3263     }
  3250   3264     if( isNT() ){
  3251   3265       int cnt = 0;
  3252   3266       WIN32_FILE_ATTRIBUTE_DATA sAttrData;
  3253   3267       memset(&sAttrData, 0, sizeof(sAttrData));
  3254   3268       while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
  3255   3269                                GetFileExInfoStandard, 
  3256         -                             &sAttrData)) && retryIoerr(&cnt) ){}
         3270  +                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
  3257   3271       if( rc ){
  3258   3272         /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
  3259   3273         ** as if it does not exist.
  3260   3274         */
  3261   3275         if(    flags==SQLITE_ACCESS_EXISTS
  3262   3276             && sAttrData.nFileSizeHigh==0 
  3263   3277             && sAttrData.nFileSizeLow==0 ){
  3264   3278           attr = INVALID_FILE_ATTRIBUTES;
  3265   3279         }else{
  3266   3280           attr = sAttrData.dwFileAttributes;
  3267   3281         }
  3268   3282       }else{
  3269         -      DWORD lastErrno = osGetLastError();
  3270   3283         logIoerr(cnt);
  3271   3284         if( lastErrno!=ERROR_FILE_NOT_FOUND ){
  3272   3285           winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
  3273   3286           sqlite3_free(zConverted);
  3274   3287           return SQLITE_IOERR_ACCESS;
  3275   3288         }else{
  3276   3289           attr = INVALID_FILE_ATTRIBUTES;