Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | In os_unix.c, do not return SQLITE_BUSY to SQLite following an error in fcntl(F_UNLCK), regardless of the value of errno. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ff6dfe6ed74f9ff1669b2bda41d61a01 |
User & Date: | dan 2011-04-01 11:56:33.000 |
Context
2011-04-01
| ||
13:29 | Move a variable declaration inside an #ifdef to avoid a compiler warning. (check-in: 7a6d05dfbc user: drh tags: trunk) | |
11:56 | In os_unix.c, do not return SQLITE_BUSY to SQLite following an error in fcntl(F_UNLCK), regardless of the value of errno. (check-in: ff6dfe6ed7 user: dan tags: trunk) | |
09:04 | Fix some problems in os_unix.c when compiled with ENABLE_LOCKING_STYLE on OSX. Also some minor issues with test scripts. (check-in: 8088031bc9 user: dan tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ return SQLITE_BUSY; } /* else fall through */ case EPERM: return SQLITE_PERM; case EDEADLK: return SQLITE_IOERR_BLOCKED; #if EOPNOTSUPP!=ENOTSUP case EOPNOTSUPP: /* something went terribly awry, unless during file system support * introspection, in which it actually means what it says */ #endif #ifdef ENOTSUP | > > > > > > > | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ return SQLITE_BUSY; } /* else fall through */ case EPERM: return SQLITE_PERM; /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And ** this module never makes such a call. And the code in SQLite itself ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons ** this case is also commented out. If the system does set errno to EDEADLK, ** the default SQLITE_IOERR_XXX code will be returned. */ #if 0 case EDEADLK: return SQLITE_IOERR_BLOCKED; #endif #if EOPNOTSUPP!=ENOTSUP case EOPNOTSUPP: /* something went terribly awry, unless during file system support * introspection, in which it actually means what it says */ #endif #ifdef ENOTSUP |
︙ | ︙ | |||
1188 1189 1190 1191 1192 1193 1194 | #ifndef __DJGPP__ if( !reserved && !pFile->pInode->bProcessLock ){ struct flock lock; lock.l_whence = SEEK_SET; lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; | | < | | | 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 | #ifndef __DJGPP__ if( !reserved && !pFile->pInode->bProcessLock ){ struct flock lock; lock.l_whence = SEEK_SET; lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ rc = SQLITE_IOERR_CHECKRESERVEDLOCK; pFile->lastErrno = errno; } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } } #endif unixLeaveMutex(); |
︙ | ︙ | |||
1421 1422 1423 1424 1425 1426 1427 | /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ /* This could happen with a network mount */ tErrno = errno; | | | 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 | /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ /* This could happen with a network mount */ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; } if( rc ){ if( rc!=SQLITE_BUSY ){ pFile->lastErrno = tErrno; } goto end_lock; |
︙ | ︙ | |||
1592 1593 1594 1595 1596 1597 1598 | lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; | | | 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } goto end_unlock; } lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; |
︙ | ︙ | |||
1616 1617 1618 1619 1620 1621 1622 | } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST+divSize; lock.l_len = SHARED_SIZE-divSize; if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; | | | > > | > > | | < < | < | < < | < | < | 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 | } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST+divSize; lock.l_len = SHARED_SIZE-divSize; if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } goto end_unlock; } }else #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ { lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; if( unixFileLock(pFile, &lock) ){ /* In theory, the call to unixFileLock() cannot fail because another ** process is holding an incompatible lock. If it does, this ** indicates that the other process is not following the locking ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning ** SQLITE_BUSY would confuse the upper layer (in practice it causes ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; pFile->lastErrno = errno; goto end_unlock; } } } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); if( unixFileLock(pFile, &lock)==0 ){ pInode->eFileLock = SHARED_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; pFile->lastErrno = errno; goto end_unlock; } } if( eFileLock==NO_LOCK ){ /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released ** the lock. */ pInode->nShared--; if( pInode->nShared==0 ){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; SimulateIOErrorBenign(1); SimulateIOError( h=(-1) ) SimulateIOErrorBenign(0); if( unixFileLock(pFile, &lock)==0 ){ pInode->eFileLock = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; pFile->lastErrno = errno; pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } } /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close |
︙ | ︙ | |||
1982 1983 1984 1985 1986 1987 1988 | /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); if( unlink(zLockFile) ){ int rc = 0; int tErrno = errno; if( ENOENT != tErrno ){ | | | 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 | /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); if( unlink(zLockFile) ){ int rc = 0; int tErrno = errno; if( ENOENT != tErrno ){ rc = SQLITE_IOERR_UNLOCK; } if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; } return rc; } pFile->eFileLock = NO_LOCK; |
︙ | ︙ | |||
2070 2071 2072 2073 2074 2075 2076 | int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); if( !lrc ){ /* got the lock, unlock it */ lrc = robust_flock(pFile->h, LOCK_UN); if ( lrc ) { int tErrno = errno; /* unlock failed with an error */ | | | 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 | int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); if( !lrc ){ /* got the lock, unlock it */ lrc = robust_flock(pFile->h, LOCK_UN); if ( lrc ) { int tErrno = errno; /* unlock failed with an error */ lrc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(lrc) ){ pFile->lastErrno = tErrno; rc = lrc; } } } else { int tErrno = errno; |
︙ | ︙ | |||
2192 2193 2194 2195 2196 2197 2198 | /* shared can just be set because we always have an exclusive */ if (eFileLock==SHARED_LOCK) { pFile->eFileLock = eFileLock; return SQLITE_OK; } /* no, really, unlock. */ | | < < < < < < < | < < | | | 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 | /* shared can just be set because we always have an exclusive */ if (eFileLock==SHARED_LOCK) { pFile->eFileLock = eFileLock; return SQLITE_OK; } /* no, really, unlock. */ if( robust_flock(pFile->h, LOCK_UN) ){ #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS return SQLITE_OK; #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ return SQLITE_IOERR_UNLOCK; }else{ pFile->eFileLock = NO_LOCK; return SQLITE_OK; } } /* ** Close a file. |
︙ | ︙ |
Changes to test/sysfault.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | } #------------------------------------------------------------------------- # Various errors in locking functions. # foreach vfs {unix unix-excl} { foreach {tn errno errlist} { | | | | | | | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | } #------------------------------------------------------------------------- # Various errors in locking functions. # foreach vfs {unix unix-excl} { foreach {tn errno errlist} { 1 EAGAIN {{database is locked} {disk I/O error}} 2 ETIMEDOUT {{database is locked} {disk I/O error}} 3 EBUSY {{database is locked} {disk I/O error}} 4 EINTR {{database is locked} {disk I/O error}} 5 ENOLCK {{database is locked} {disk I/O error}} 6 EACCES {{database is locked} {disk I/O error}} 7 EPERM {{access permission denied} {disk I/O error}} 8 EDEADLK {{disk I/O error}} 9 ENOMEM {{disk I/O error}} } { proc vfsfault_install {} { test_syscall install fcntl } set errs [list] foreach e $errlist { lappend errs [list 1 $e] } |
︙ | ︙ |