/ Check-in [8609a15d]
Login

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

Overview
Comment:Automatically retry system calls that fail with EINTR. This is a backport of the changes from [b9d29ea385bafc] and [af9ba2a6d2c379].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | branch-3.7.4
Files: files | file ages | folders
SHA1: 8609a15dfad23a7c5311b52617d5c4818c0b8d1e
User & Date: drh 2011-02-23 14:33:31
Context
2011-02-23
14:33
Automatically retry system calls that fail with EINTR. This is a backport of the changes from [b9d29ea385bafc] and [af9ba2a6d2c379]. Leaf check-in: 8609a15d user: drh tags: branch-3.7.4
14:05
Backport the os_unix.c error logging enhancements from check-in [01076528a43b61a]. check-in: a4333b15 user: drh tags: branch-3.7.4
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

   390    390     errno = savedErrno;
   391    391     return s;
   392    392   }
   393    393   #define fcntl lockTrace
   394    394   #endif /* SQLITE_LOCK_TRACE */
   395    395   
   396    396   
          397  +/*
          398  +** Retry ftruncate() calls that fail due to EINTR
          399  +*/
          400  +#ifdef EINTR
          401  +static int robust_ftruncate(int h, sqlite3_int64 sz){
          402  +  int rc;
          403  +  do{ rc = ftruncate(h,sz); }while( rc<0 && errno==EINTR );
          404  +  return rc;
          405  +}
          406  +#else
          407  +# define robust_ftruncate(a,b) ftruncate(a,b)
          408  +#endif 
          409  +
   397    410   
   398    411   /*
   399    412   ** This routine translates a standard POSIX errno code into something
   400    413   ** useful to the clients of the sqlite3 functions.  Specifically, it is
   401    414   ** intended to translate a variety of "try again" errors into SQLITE_BUSY
   402    415   ** and a variety of "please close the file descriptor NOW" errors into 
   403    416   ** SQLITE_IOERR
................................................................................
   908    921     ** prior to accessing the inode number.  The one byte written is
   909    922     ** an ASCII 'S' character which also happens to be the first byte
   910    923     ** in the header of every SQLite database.  In this way, if there
   911    924     ** is a race condition such that another thread has already populated
   912    925     ** the first page of the database, no damage is done.
   913    926     */
   914    927     if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
   915         -    rc = write(fd, "S", 1);
          928  +    do{ rc = write(fd, "S", 1); }while( rc<0 && errno==EINTR );
   916    929       if( rc!=1 ){
   917    930         pFile->lastErrno = errno;
   918    931         return SQLITE_IOERR;
   919    932       }
   920    933       rc = fstat(fd, &statbuf);
   921    934       if( rc!=0 ){
   922    935         pFile->lastErrno = errno;
................................................................................
  1784   1797   ** only a single process can be reading the database at a time.
  1785   1798   **
  1786   1799   ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
  1787   1800   ** compiling for VXWORKS.
  1788   1801   */
  1789   1802   #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
  1790   1803   
         1804  +/*
         1805  +** Retry flock() calls that fail with EINTR
         1806  +*/
         1807  +#ifdef EINTR
         1808  +static int robust_flock(int fd, int op){
         1809  +  int rc;
         1810  +  do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
         1811  +  return rc;
         1812  +}
         1813  +#else
         1814  +# define robust_flock(a,b) flock(a,b)
         1815  +#endif
         1816  +     
         1817  +
  1791   1818   /*
  1792   1819   ** This routine checks if there is a RESERVED lock held on the specified
  1793   1820   ** file by this or any other process. If such a lock is held, set *pResOut
  1794   1821   ** to a non-zero value otherwise *pResOut is set to zero.  The return value
  1795   1822   ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
  1796   1823   */
  1797   1824   static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
................................................................................
  1807   1834     if( pFile->eFileLock>SHARED_LOCK ){
  1808   1835       reserved = 1;
  1809   1836     }
  1810   1837     
  1811   1838     /* Otherwise see if some other process holds it. */
  1812   1839     if( !reserved ){
  1813   1840       /* attempt to get the lock */
  1814         -    int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
         1841  +    int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
  1815   1842       if( !lrc ){
  1816   1843         /* got the lock, unlock it */
  1817         -      lrc = flock(pFile->h, LOCK_UN);
         1844  +      lrc = robust_flock(pFile->h, LOCK_UN);
  1818   1845         if ( lrc ) {
  1819   1846           int tErrno = errno;
  1820   1847           /* unlock failed with an error */
  1821   1848           lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
  1822   1849           if( IS_LOCK_ERROR(lrc) ){
  1823   1850             pFile->lastErrno = tErrno;
  1824   1851             rc = lrc;
................................................................................
  1887   1914     if (pFile->eFileLock > NO_LOCK) {
  1888   1915       pFile->eFileLock = eFileLock;
  1889   1916       return SQLITE_OK;
  1890   1917     }
  1891   1918     
  1892   1919     /* grab an exclusive lock */
  1893   1920     
  1894         -  if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
         1921  +  if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
  1895   1922       int tErrno = errno;
  1896   1923       /* didn't get, must be busy */
  1897   1924       rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1898   1925       if( IS_LOCK_ERROR(rc) ){
  1899   1926         pFile->lastErrno = tErrno;
  1900   1927       }
  1901   1928     } else {
................................................................................
  1936   1963     /* shared can just be set because we always have an exclusive */
  1937   1964     if (eFileLock==SHARED_LOCK) {
  1938   1965       pFile->eFileLock = eFileLock;
  1939   1966       return SQLITE_OK;
  1940   1967     }
  1941   1968     
  1942   1969     /* no, really, unlock. */
  1943         -  int rc = flock(pFile->h, LOCK_UN);
         1970  +  int rc = robust_flock(pFile->h, LOCK_UN);
  1944   1971     if (rc) {
  1945   1972       int r, tErrno = errno;
  1946   1973       r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1947   1974       if( IS_LOCK_ERROR(r) ){
  1948   1975         pFile->lastErrno = tErrno;
  1949   1976       }
  1950   1977   #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
................................................................................
  2673   2700   static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
  2674   2701     int got;
  2675   2702   #if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  2676   2703     i64 newOffset;
  2677   2704   #endif
  2678   2705     TIMER_START;
  2679   2706   #if defined(USE_PREAD)
  2680         -  got = pread(id->h, pBuf, cnt, offset);
         2707  +  do{ got = pread(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
  2681   2708     SimulateIOError( got = -1 );
  2682   2709   #elif defined(USE_PREAD64)
  2683         -  got = pread64(id->h, pBuf, cnt, offset);
         2710  +  do{ got = pread64(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
  2684   2711     SimulateIOError( got = -1 );
  2685   2712   #else
  2686   2713     newOffset = lseek(id->h, offset, SEEK_SET);
  2687   2714     SimulateIOError( newOffset-- );
  2688   2715     if( newOffset!=offset ){
  2689   2716       if( newOffset == -1 ){
  2690   2717         ((unixFile*)id)->lastErrno = errno;
  2691   2718       }else{
  2692   2719         ((unixFile*)id)->lastErrno = 0;			
  2693   2720       }
  2694   2721       return -1;
  2695   2722     }
  2696         -  got = read(id->h, pBuf, cnt);
         2723  +  do{ got = read(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
  2697   2724   #endif
  2698   2725     TIMER_END;
  2699   2726     if( got<0 ){
  2700   2727       ((unixFile*)id)->lastErrno = errno;
  2701   2728     }
  2702   2729     OSTRACE(("READ    %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
  2703   2730     return got;
................................................................................
  2751   2778   static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
  2752   2779     int got;
  2753   2780   #if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  2754   2781     i64 newOffset;
  2755   2782   #endif
  2756   2783     TIMER_START;
  2757   2784   #if defined(USE_PREAD)
  2758         -  got = pwrite(id->h, pBuf, cnt, offset);
         2785  +  do{ got = pwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
  2759   2786   #elif defined(USE_PREAD64)
  2760         -  got = pwrite64(id->h, pBuf, cnt, offset);
         2787  +  do{ got = pwrite64(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
  2761   2788   #else
  2762   2789     newOffset = lseek(id->h, offset, SEEK_SET);
  2763   2790     if( newOffset!=offset ){
  2764   2791       if( newOffset == -1 ){
  2765   2792         ((unixFile*)id)->lastErrno = errno;
  2766   2793       }else{
  2767   2794         ((unixFile*)id)->lastErrno = 0;			
  2768   2795       }
  2769   2796       return -1;
  2770   2797     }
  2771         -  got = write(id->h, pBuf, cnt);
         2798  +  do{ got = write(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
  2772   2799   #endif
  2773   2800     TIMER_END;
  2774   2801     if( got<0 ){
  2775   2802       ((unixFile*)id)->lastErrno = errno;
  2776   2803     }
  2777   2804   
  2778   2805     OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
................................................................................
  3055   3082     ** actual file size after the operation may be larger than the requested
  3056   3083     ** size).
  3057   3084     */
  3058   3085     if( pFile->szChunk ){
  3059   3086       nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  3060   3087     }
  3061   3088   
  3062         -  rc = ftruncate(pFile->h, (off_t)nByte);
         3089  +  rc = robust_ftruncate(pFile->h, (off_t)nByte);
  3063   3090     if( rc ){
  3064   3091       pFile->lastErrno = errno;
  3065   3092       return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
  3066   3093     }else{
  3067   3094   #ifndef NDEBUG
  3068   3095       /* If we are doing a normal write to a database file (as opposed to
  3069   3096       ** doing a hot-journal rollback or a write to some file other than a
................................................................................
  3130   3157       struct stat buf;              /* Used to hold return values of fstat() */
  3131   3158      
  3132   3159       if( fstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
  3133   3160   
  3134   3161       nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
  3135   3162       if( nSize>(i64)buf.st_size ){
  3136   3163   #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  3137         -      if( posix_fallocate(pFile->h, buf.st_size, nSize-buf.st_size) ){
  3138         -        return SQLITE_IOERR_WRITE;
  3139         -      }
         3164  +      int rc;
         3165  +      do{
         3166  +        rc = posix_fallocate(pFile-.h, buf.st_size, nSize-buf.st_size;
         3167  +      }while( rc<0 && errno=EINTR );
         3168  +      if( rc ) return SQLITE_IOERR_WRITE;
  3140   3169   #else
  3141   3170         /* If the OS does not have posix_fallocate(), fake it. First use
  3142   3171         ** ftruncate() to set the file size, then write a single byte to
  3143   3172         ** the last byte in each block within the extended region. This
  3144   3173         ** is the same technique used by glibc to implement posix_fallocate()
  3145   3174         ** on systems that do not have a real fallocate() system call.
  3146   3175         */
  3147   3176         int nBlk = buf.st_blksize;  /* File-system block size */
  3148   3177         i64 iWrite;                 /* Next offset to write to */
  3149   3178         int nWrite;                 /* Return value from seekAndWrite() */
  3150   3179   
  3151         -      if( ftruncate(pFile->h, nSize) ){
         3180  +      if( robust_ftruncate(pFile->h, nSize) ){
  3152   3181           pFile->lastErrno = errno;
  3153   3182           return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
  3154   3183         }
  3155   3184         iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
  3156   3185         do {
  3157   3186           nWrite = seekAndWrite(pFile, iWrite, "", 1);
  3158   3187           iWrite += nBlk;
................................................................................
  3501   3530       }
  3502   3531   
  3503   3532       /* Check to see if another process is holding the dead-man switch.
  3504   3533       ** If not, truncate the file to zero length. 
  3505   3534       */
  3506   3535       rc = SQLITE_OK;
  3507   3536       if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
  3508         -      if( ftruncate(pShmNode->h, 0) ){
         3537  +      if( robust_ftruncate(pShmNode->h, 0) ){
  3509   3538           rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
  3510   3539         }
  3511   3540       }
  3512   3541       if( rc==SQLITE_OK ){
  3513   3542         rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
  3514   3543       }
  3515   3544       if( rc ) goto shm_open_err;
................................................................................
  3607   3636         /* The requested memory region does not exist. If bExtend is set to
  3608   3637         ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
  3609   3638         **
  3610   3639         ** Alternatively, if bExtend is true, use ftruncate() to allocate
  3611   3640         ** the requested memory region.
  3612   3641         */
  3613   3642         if( !bExtend ) goto shmpage_out;
  3614         -      if( ftruncate(pShmNode->h, nByte) ){
         3643  +      if( robust_ftruncate(pShmNode->h, nByte) ){
  3615   3644           rc = unixLogError(SQLITE_IOERR_SHMSIZE,"ftruncate",pShmNode->zFilename);
  3616   3645           goto shmpage_out;
  3617   3646         }
  3618   3647       }
  3619   3648   
  3620   3649       /* Map the requested memory region into this processes address space. */
  3621   3650       apNew = (char **)sqlite3_realloc(
................................................................................
  5004   5033         time(&t);
  5005   5034         memcpy(zBuf, &t, sizeof(t));
  5006   5035         pid = getpid();
  5007   5036         memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
  5008   5037         assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
  5009   5038         nBuf = sizeof(t) + sizeof(pid);
  5010   5039       }else{
  5011         -      nBuf = read(fd, zBuf, nBuf);
         5040  +      do{ nBuf = read(fd, zBuf, nBuf); }while( nBuf<0 && errno==EINTR );
  5012   5041         close(fd);
  5013   5042       }
  5014   5043     }
  5015   5044   #endif
  5016   5045     return nBuf;
  5017   5046   }
  5018   5047   
................................................................................
  5764   5793           memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
  5765   5794           if( pCtx->lockProxyPath!=NULL ){
  5766   5795             strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
  5767   5796           }else{
  5768   5797             strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
  5769   5798           }
  5770   5799           writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
  5771         -        ftruncate(conchFile->h, writeSize);
         5800  +        robust_ftruncate(conchFile->h, writeSize);
  5772   5801           rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
  5773   5802           fsync(conchFile->h);
  5774   5803           /* If we created a new conch file (not just updated the contents of a 
  5775   5804            ** valid conch file), try to match the permissions of the database 
  5776   5805            */
  5777   5806           if( rc==SQLITE_OK && createConch ){
  5778   5807             struct stat buf;
         5808  +          int rc;
  5779   5809             int err = fstat(pFile->h, &buf);
  5780   5810             if( err==0 ){
  5781   5811               mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
  5782   5812                                           S_IROTH|S_IWOTH);
  5783   5813               /* try to match the database file R/W permissions, ignore failure */
  5784   5814   #ifndef SQLITE_PROXY_DEBUG
  5785   5815               fchmod(conchFile->h, cmode);
  5786   5816   #else
  5787         -            if( fchmod(conchFile->h, cmode)!=0 ){
         5817  +            do{
         5818  +              rc = fchmod(conchFile->h, cmode);
         5819  +            }while( rc==(-1) && errno==EINTR );
         5820  +            if( rc!=0 ){
  5788   5821                 int code = errno;
  5789   5822                 fprintf(stderr, "fchmod %o FAILED with %d %s\n",
  5790   5823                         cmode, code, strerror(code));
  5791   5824               } else {
  5792   5825                 fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
  5793   5826               }
  5794   5827             }else{