/ Check-in [7e657bbb]
Login

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

Overview
Comment:Cleanup the semantics surrounding use of the GetLastError function on Windows.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | winGetLastError
Files: files | file ages | folders
SHA1: 7e657bbb800107c992a6ee7a3b35bc0a073bf3e4
User & Date: mistachkin 2011-11-21 00:54:37
Context
2011-12-06
00:47
Merge the winGetLastError fixes into trunk. check-in: 5b03ba9d 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
2011-11-18
13:10
Change the multiplexor to use a 3-digit suffix. check-in: 0b7edc44 user: drh tags: trunk
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;