/ Check-in [2e54a743]
Login

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

Overview
Comment:Add infrastructure to support for using F_SETLKW with a timeout on system that support that functionality. Requires SQLITE_ENABLE_SETLK_TIMEOUT.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lowlevel-lock-timeout
Files: files | file ages | folders
SHA3-256: 2e54a7433ece4eb27e71bda6f2d121d5aa46ddd5a481357d8543d1432aaad689
User & Date: drh 2018-03-26 17:40:53
Context
2018-03-26
20:43
Avoid a race condition that might cause a busy_timeout to last longer than it should. check-in: b8196056 user: drh tags: lowlevel-lock-timeout
17:40
Add infrastructure to support for using F_SETLKW with a timeout on system that support that functionality. Requires SQLITE_ENABLE_SETLK_TIMEOUT. check-in: 2e54a743 user: drh tags: lowlevel-lock-timeout
16:37
Refactor some internal object element names used by the busy handler, to simplify analysis. check-in: 6c40c557 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  2227   2227   /*
  2228   2228   ** Invoke the busy handler for a btree.
  2229   2229   */
  2230   2230   static int btreeInvokeBusyHandler(void *pArg){
  2231   2231     BtShared *pBt = (BtShared*)pArg;
  2232   2232     assert( pBt->db );
  2233   2233     assert( sqlite3_mutex_held(pBt->db->mutex) );
  2234         -  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
         2234  +  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
         2235  +                                  sqlite3PagerFile(pBt->pPager));
  2235   2236   }
  2236   2237   
  2237   2238   /*
  2238   2239   ** Open a database file.
  2239   2240   ** 
  2240   2241   ** zFilename is the name of the database file.  If zFilename is NULL
  2241   2242   ** then an ephemeral database is created.  The ephemeral database might

Changes to src/main.c.

  1472   1472   }
  1473   1473   
  1474   1474   /*
  1475   1475   ** This routine implements a busy callback that sleeps and tries
  1476   1476   ** again until a timeout value is reached.  The timeout value is
  1477   1477   ** an integer number of milliseconds passed in as the first
  1478   1478   ** argument.
         1479  +**
         1480  +** Return non-zero to retry the lock.  Return zero to stop trying
         1481  +** and cause SQLite to return SQLITE_BUSY.
  1479   1482   */
  1480   1483   static int sqliteDefaultBusyCallback(
  1481         - void *ptr,               /* Database connection */
  1482         - int count                /* Number of times table has been busy */
         1484  +  void *ptr,               /* Database connection */
         1485  +  int count,               /* Number of times table has been busy */
         1486  +  sqlite3_file *pFile      /* The file on which the lock occurred */
  1483   1487   ){
  1484   1488   #if SQLITE_OS_WIN || HAVE_USLEEP
         1489  +  /* This case is for systems that have support for sleeping for fractions of
         1490  +  ** a second.  Examples:  All windows systems, unix systems with usleep() */
  1485   1491     static const u8 delays[] =
  1486   1492        { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50, 100 };
  1487   1493     static const u8 totals[] =
  1488   1494        { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228 };
  1489   1495   # define NDELAY ArraySize(delays)
  1490   1496     sqlite3 *db = (sqlite3 *)ptr;
  1491         -  int timeout = db->busyTimeout;
         1497  +  int tmout = db->busyTimeout;
  1492   1498     int delay, prior;
  1493   1499   
         1500  +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
         1501  +  if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
         1502  +    if( count ){
         1503  +      tmout = 0;
         1504  +      sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
         1505  +      return 0;
         1506  +    }else{
         1507  +      return 1;
         1508  +    }
         1509  +  }
         1510  +#endif
  1494   1511     assert( count>=0 );
  1495   1512     if( count < NDELAY ){
  1496   1513       delay = delays[count];
  1497   1514       prior = totals[count];
  1498   1515     }else{
  1499   1516       delay = delays[NDELAY-1];
  1500   1517       prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
  1501   1518     }
  1502         -  if( prior + delay > timeout ){
  1503         -    delay = timeout - prior;
         1519  +  if( prior + delay > tmout ){
         1520  +    delay = tmout - prior;
  1504   1521       if( delay<=0 ) return 0;
  1505   1522     }
  1506   1523     sqlite3OsSleep(db->pVfs, delay*1000);
  1507   1524     return 1;
  1508   1525   #else
         1526  +  /* This case for unix systems that lack usleep() support.  Sleeping
         1527  +  ** must be done in increments of whole seconds */
  1509   1528     sqlite3 *db = (sqlite3 *)ptr;
  1510         -  int timeout = ((sqlite3 *)ptr)->busyTimeout;
  1511         -  if( (count+1)*1000 > timeout ){
         1529  +  int tmout = ((sqlite3 *)ptr)->busyTimeout;
         1530  +  if( (count+1)*1000 > tmout ){
  1512   1531       return 0;
  1513   1532     }
  1514   1533     sqlite3OsSleep(db->pVfs, 1000000);
  1515   1534     return 1;
  1516   1535   #endif
  1517   1536   }
  1518   1537   
  1519   1538   /*
  1520   1539   ** Invoke the given busy handler.
  1521   1540   **
  1522         -** This routine is called when an operation failed with a lock.
         1541  +** This routine is called when an operation failed to acquire a
         1542  +** lock on VFS file pFile.
         1543  +**
  1523   1544   ** If this routine returns non-zero, the lock is retried.  If it
  1524   1545   ** returns 0, the operation aborts with an SQLITE_BUSY error.
  1525   1546   */
  1526         -int sqlite3InvokeBusyHandler(BusyHandler *p){
         1547  +int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
  1527   1548     int rc;
  1528   1549     if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
  1529         -  rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
         1550  +  if( p->bExtraFileArg ){
         1551  +    /* Add an extra parameter with the pFile pointer to the end of the
         1552  +    ** callback argument list */
         1553  +    int (*xTra)(void*,int,sqlite3_file*);
         1554  +    xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
         1555  +    rc = xTra(p->pBusyArg, p->nBusy, pFile);
         1556  +  }else{
         1557  +    /* Legacy style busy handler callback */
         1558  +    rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
         1559  +  }
  1530   1560     if( rc==0 ){
  1531   1561       p->nBusy = -1;
  1532   1562     }else{
  1533   1563       p->nBusy++;
  1534   1564     }
  1535   1565     return rc; 
  1536   1566   }
................................................................................
  1547   1577   #ifdef SQLITE_ENABLE_API_ARMOR
  1548   1578     if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  1549   1579   #endif
  1550   1580     sqlite3_mutex_enter(db->mutex);
  1551   1581     db->busyHandler.xBusyHandler = xBusy;
  1552   1582     db->busyHandler.pBusyArg = pArg;
  1553   1583     db->busyHandler.nBusy = 0;
         1584  +  db->busyHandler.bExtraFileArg = 0;
  1554   1585     db->busyTimeout = 0;
  1555   1586     sqlite3_mutex_leave(db->mutex);
  1556   1587     return SQLITE_OK;
  1557   1588   }
  1558   1589   
  1559   1590   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  1560   1591   /*
................................................................................
  1594   1625   ** specified number of milliseconds before returning 0.
  1595   1626   */
  1596   1627   int sqlite3_busy_timeout(sqlite3 *db, int ms){
  1597   1628   #ifdef SQLITE_ENABLE_API_ARMOR
  1598   1629     if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  1599   1630   #endif
  1600   1631     if( ms>0 ){
  1601         -    sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
         1632  +    sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
         1633  +                             (void*)db);
  1602   1634       db->busyTimeout = ms;
         1635  +    db->busyHandler.bExtraFileArg = 1;
  1603   1636     }else{
  1604   1637       sqlite3_busy_handler(db, 0, 0);
  1605   1638     }
  1606   1639     return SQLITE_OK;
  1607   1640   }
  1608   1641   
  1609   1642   /*

Changes to src/os_unix.c.

   225    225     int deviceCharacteristics;          /* Precomputed device characteristics */
   226    226   #if SQLITE_ENABLE_LOCKING_STYLE
   227    227     int openFlags;                      /* The flags specified at open() */
   228    228   #endif
   229    229   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   230    230     unsigned fsFlags;                   /* cached details from statfs() */
   231    231   #endif
          232  +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
          233  +  unsigned iBusyTimeout;              /* Wait this many millisec on locks */
          234  +#endif
   232    235   #if OS_VXWORKS
   233    236     struct vxworksFileId *pId;          /* Unique file ID */
   234    237   #endif
   235    238   #ifdef SQLITE_DEBUG
   236    239     /* The next group of variables are used to track whether or not the
   237    240     ** transaction counter in bytes 24-27 of database files are updated
   238    241     ** whenever any part of the database changes.  An assertion fault will
................................................................................
  1460   1463     
  1461   1464     unixLeaveMutex();
  1462   1465     OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
  1463   1466   
  1464   1467     *pResOut = reserved;
  1465   1468     return rc;
  1466   1469   }
         1470  +
         1471  +/*
         1472  +** Set a posix-advisory-lock.
         1473  +**
         1474  +** There are two versions of this routine.  If compiled with
         1475  +** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
         1476  +** which is a pointer to a unixFile.  If the unixFile->iBusyTimeout
         1477  +** value is set, then it is the number of milliseconds to wait before
         1478  +** failing the lock.  The iBusyTimeout value is always reset back to
         1479  +** zero on each call.
         1480  +**
         1481  +** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
         1482  +** attempt to set the lock.
         1483  +*/
         1484  +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
         1485  +# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
         1486  +#else
         1487  +static int osSetPosixAdvisoryLock(
         1488  +  int h,                /* The file descriptor on which to take the lock */
         1489  +  struct flock *pLock,  /* The description of the lock */
         1490  +  unixFile *pFile       /* Structure holding timeout value */
         1491  +){
         1492  +  int rc = osFcntl(h,F_SETLK,pLock);
         1493  +  if( rc<0 && pFile->iBusyTimeout>0 ){
         1494  +    /* On systems that support some kind of blocking file lock with a timeout,
         1495  +    ** make appropriate changes here to invoke that blocking file lock.  On
         1496  +    ** generic posix, however, there is no such API.  So we simply try the
         1497  +    ** lock once every millisecond until either the timeout expires, or until
         1498  +    ** the lock is obtained. */
         1499  +    do{
         1500  +      usleep(1000);
         1501  +      rc = osFcntl(h,F_SETLK,pLock);
         1502  +      pFile->iBusyTimeout--;
         1503  +    }while( rc<0 && pFile->iBusyTimeout>0 );
         1504  +    pFile->iBusyTimeout = 0;
         1505  +  }
         1506  +  return rc;
         1507  +}
         1508  +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
         1509  +
  1467   1510   
  1468   1511   /*
  1469   1512   ** Attempt to set a system-lock on the file pFile.  The lock is 
  1470   1513   ** described by pLock.
  1471   1514   **
  1472   1515   ** If the pFile was opened read/write from unix-excl, then the only lock
  1473   1516   ** ever obtained is an exclusive lock, and it is obtained exactly once
................................................................................
  1493   1536       if( pInode->bProcessLock==0 ){
  1494   1537         struct flock lock;
  1495   1538         assert( pInode->nLock==0 );
  1496   1539         lock.l_whence = SEEK_SET;
  1497   1540         lock.l_start = SHARED_FIRST;
  1498   1541         lock.l_len = SHARED_SIZE;
  1499   1542         lock.l_type = F_WRLCK;
  1500         -      rc = osFcntl(pFile->h, F_SETLK, &lock);
         1543  +      rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
  1501   1544         if( rc<0 ) return rc;
  1502   1545         pInode->bProcessLock = 1;
  1503   1546         pInode->nLock++;
  1504   1547       }else{
  1505   1548         rc = 0;
  1506   1549       }
  1507   1550     }else{
  1508         -    rc = osFcntl(pFile->h, F_SETLK, pLock);
         1551  +    rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
  1509   1552     }
  1510   1553     return rc;
  1511   1554   }
  1512   1555   
  1513   1556   /*
  1514   1557   ** Lock the file with the lock specified by parameter eFileLock - one
  1515   1558   ** of the following:
................................................................................
  3861   3904         }
  3862   3905         return SQLITE_OK;
  3863   3906       }
  3864   3907       case SQLITE_FCNTL_HAS_MOVED: {
  3865   3908         *(int*)pArg = fileHasMoved(pFile);
  3866   3909         return SQLITE_OK;
  3867   3910       }
         3911  +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
         3912  +    case SQLITE_FCNTL_LOCK_TIMEOUT: {
         3913  +      pFile->iBusyTimeout = *(int*)pArg;
         3914  +      return SQLITE_OK;
         3915  +    }
         3916  +#endif
  3868   3917   #if SQLITE_MAX_MMAP_SIZE>0
  3869   3918       case SQLITE_FCNTL_MMAP_SIZE: {
  3870   3919         i64 newLimit = *(i64*)pArg;
  3871   3920         int rc = SQLITE_OK;
  3872   3921         if( newLimit>sqlite3GlobalConfig.mxMmap ){
  3873   3922           newLimit = sqlite3GlobalConfig.mxMmap;
  3874   3923         }
................................................................................
  4180   4229   
  4181   4230     if( pShmNode->h>=0 ){
  4182   4231       /* Initialize the locking parameters */
  4183   4232       f.l_type = lockType;
  4184   4233       f.l_whence = SEEK_SET;
  4185   4234       f.l_start = ofst;
  4186   4235       f.l_len = n;
  4187         -    rc = osFcntl(pShmNode->h, F_SETLK, &f);
         4236  +    rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
  4188   4237       rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
  4189   4238     }
  4190   4239   
  4191   4240     /* Update the global lock state and do debug tracing */
  4192   4241   #ifdef SQLITE_DEBUG
  4193   4242     { u16 mask;
  4194   4243     OSTRACE(("SHM-LOCK "));

Changes to src/sqlite.h.in.

  1060   1060   ** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
  1061   1061   ** operations since the previous successful call to 
  1062   1062   ** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
  1063   1063   ** ^This file control takes the file descriptor out of batch write mode
  1064   1064   ** so that all subsequent write operations are independent.
  1065   1065   ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
  1066   1066   ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
         1067  +**
         1068  +** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
         1069  +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
         1070  +** a file lock using the xLock or xShmLock methods of the VFS to wait
         1071  +** for up to M milliseconds before failing, where M is the single 
         1072  +** unsigned integer parameter.
  1067   1073   ** </ul>
  1068   1074   */
  1069   1075   #define SQLITE_FCNTL_LOCKSTATE               1
  1070   1076   #define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
  1071   1077   #define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
  1072   1078   #define SQLITE_FCNTL_LAST_ERRNO              4
  1073   1079   #define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
  1094   1100   #define SQLITE_FCNTL_VFS_POINTER            27
  1095   1101   #define SQLITE_FCNTL_JOURNAL_POINTER        28
  1096   1102   #define SQLITE_FCNTL_WIN32_GET_HANDLE       29
  1097   1103   #define SQLITE_FCNTL_PDB                    30
  1098   1104   #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
  1099   1105   #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
  1100   1106   #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
         1107  +#define SQLITE_FCNTL_LOCK_TIMEOUT           34
         1108  +#define SQLITE_FCNTL_LAST                   34 /* Last value */
  1101   1109   
  1102   1110   /* deprecated names */
  1103   1111   #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
  1104   1112   #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
  1105   1113   #define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
  1106   1114   
  1107   1115   

Changes to src/sqliteInt.h.

   960    960   ** callback is currently invoked only from within pager.c.
   961    961   */
   962    962   typedef struct BusyHandler BusyHandler;
   963    963   struct BusyHandler {
   964    964     int (*xBusyHandler)(void *,int);  /* The busy callback */
   965    965     void *pBusyArg;                   /* First arg to busy callback */
   966    966     int nBusy;                        /* Incremented with each busy call */
          967  +  u8 bExtraFileArg;                 /* Include sqlite3_file as callback arg */
   967    968   };
   968    969   
   969    970   /*
   970    971   ** Name of the master database table.  The master database table
   971    972   ** is a special table that holds the names and attributes of all
   972    973   ** user tables and indices.
   973    974   */
................................................................................
  4099   4100   int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
  4100   4101   void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
  4101   4102   void sqlite3AlterFinishAddColumn(Parse *, Token *);
  4102   4103   void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
  4103   4104   CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
  4104   4105   char sqlite3AffinityType(const char*, u8*);
  4105   4106   void sqlite3Analyze(Parse*, Token*, Token*);
  4106         -int sqlite3InvokeBusyHandler(BusyHandler*);
         4107  +int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
  4107   4108   int sqlite3FindDb(sqlite3*, Token*);
  4108   4109   int sqlite3FindDbName(sqlite3 *, const char *);
  4109   4110   int sqlite3AnalysisLoad(sqlite3*,int iDB);
  4110   4111   void sqlite3DeleteIndexSamples(sqlite3*,Index*);
  4111   4112   void sqlite3DefaultRowEst(Index*);
  4112   4113   void sqlite3RegisterLikeFunctions(sqlite3*, int);
  4113   4114   int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);