From: drh Date: Thu, 29 Apr 2010 16:40:51 +0000 (+0000) Subject: Untested implementation of the shared-memory dead-man-switch. X-Git-Tag: version-3.7.2~455^2~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=31cbbbad1ccf37ad2f83daf2b34416e643f75d3e;p=thirdparty%2Fsqlite.git Untested implementation of the shared-memory dead-man-switch. FossilOrigin-Name: 706611283ea2575c2942543391026b36061cfc1c --- diff --git a/manifest b/manifest index 81762c0b4c..ee0cee40d9 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Progress\stowards\sa\sVFS\sthat\swill\ssupport\sWAL.\s\sLocking\scode\sis\sin\splace\nbut\sis\suntested.\s\sStill\sno\ssupport\sfor\sthe\sDMS. -D 2010-04-29T15:17:48 +C Untested\simplementation\sof\sthe\sshared-memory\sdead-man-switch. +D 2010-04-29T16:40:51 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -153,7 +153,7 @@ F src/os.c 8bc63cf91e9802e2b807198e54e50227fa889306 F src/os.h 534b082c3cb349ad05fa6fa0b06087e022af282c F src/os_common.h 0d6ee583b6ee3185eb9d951f890c6dd03021a08d F src/os_os2.c 8ad77a418630d7dee91d1bb04f79c2096301d3a0 -F src/os_unix.c 340c503705cdb447753a55771911a92aa41d27c8 +F src/os_unix.c f0e002e74108c8a3f70c63dd91419ab6bcafd095 F src/os_win.c a8fc01d8483be472e495793c01064fd87e56a5c1 F src/pager.c b4a41030860229e80295fa1f37addab24d21799c F src/pager.h cee4487ab4f0911dd9f22a40e3cd55afdb7ef444 @@ -811,14 +811,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3cc55a7568daa3796483f632e33478969e381cf5 -R 1f2ad602233779dda1e35a2877201d1f +P 1bde41cf081570ad257f927b641e752dff4ed014 +R a7ee89d9d5eb7d4f4fd9d69824beab31 U drh -Z 5bb08c68390b552fdeb1ef93301ae98c +Z 15bd57757c5a0ce16c3065e9d45dae67 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFL2aMhoxKgR168RlERAntLAKCNwNXdF9LrZZqkEN8f3gsvrSxoXACaA2Ku -SvIawhrGV2wraxrir5MNan8= -=Vfpz +iD4DBQFL2baVoxKgR168RlERArO2AJ9g8Vnb6XlVDltcg68idEyJzFPcYwCYh7Xs +0Mdctk0jP1xbHiTJhHLX+A== +=minX -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 000aaadb5f..ca7b008f92 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1bde41cf081570ad257f927b641e752dff4ed014 \ No newline at end of file +706611283ea2575c2942543391026b36061cfc1c \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 634f5ee218..248309664d 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4698,7 +4698,7 @@ static const char *unixShmLockString(u8 mask){ ** Locks block if the UNIX_SHM_MUTEX bit is set and are non-blocking ** otherwise. */ -static int unixShmSystemLocks( +static int unixShmSystemLock( unixShmFile *pFile, /* Apply locks to this open shared-memory segment */ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ u8 lockMask /* Which bytes to lock or unlock */ @@ -4709,6 +4709,9 @@ static int unixShmSystemLocks( int rc; /* Result code form fcntl() */ u8 mask; /* Mask of bits in lockMask */ + /* Access to the unixShmFile object is serialized by the caller */ + assert( sqlite3_mutex_held(pFile->mutex) ); + /* Initialize the locking parameters */ memset(&f, 0, sizeof(f)); f.l_type = lockType; @@ -4787,6 +4790,9 @@ static int unixShmUnlock( unixShm *pX; /* For looping over all sibling connections */ u8 allMask; /* Union of locks held by connections other than "p" */ + /* Access to the unixShmFile object is serialized by the caller */ + assert( sqlite3_mutex_held(pFile->mutex) ); + /* We never try to unlock locks that we do not hold */ assert( ((p->exclMask|p->sharedMask) & unlockMask)==unlockMask ); @@ -4799,7 +4805,7 @@ static int unixShmUnlock( /* Unlock the system-level locks */ if( (unlockMask & allMask)!=unlockMask ){ - rc = unixShmSystemLocks(pFile, F_UNLCK, unlockMask & ~allMask); + rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask); }else{ rc = SQLITE_OK; } @@ -4824,6 +4830,9 @@ static int unixShmSharedLock( unixShm *pX; /* For looping over all sibling connections */ u8 allShared; /* Union of locks held by connections other than "p" */ + /* Access to the unixShmFile object is serialized by the caller */ + assert( sqlite3_mutex_held(pFile->mutex) ); + /* Find out which shared locks are already held by sibling connections. ** If any sibling already holds an exclusive lock, go ahead and return ** SQLITE_BUSY. @@ -4836,7 +4845,7 @@ static int unixShmSharedLock( /* Get shared locks at the system level, if necessary */ if( (~allShared) & readMask ){ - rc = unixShmSystemLocks(pFile, F_RDLCK, readMask); + rc = unixShmSystemLock(pFile, F_RDLCK, readMask); }else{ rc = SQLITE_OK; } @@ -4860,6 +4869,9 @@ static int unixShmExclusiveLock( int rc; /* Result code */ unixShm *pX; /* For looping over all sibling connections */ + /* Access to the unixShmFile object is serialized by the caller */ + assert( sqlite3_mutex_held(pFile->mutex) ); + /* Make sure no sibling connections hold locks that will block this ** lock. If any do, return SQLITE_BUSY right away. */ @@ -4872,7 +4884,7 @@ static int unixShmExclusiveLock( /* Get the exclusive locks at the system level. Then if successful ** also mark the local connection as being locked. */ - rc = unixShmSystemLocks(pFile, F_WRLCK, writeMask); + rc = unixShmSystemLock(pFile, F_WRLCK, writeMask); if( rc==SQLITE_OK ){ p->sharedMask &= ~writeMask; p->exclMask |= writeMask; @@ -4917,16 +4929,20 @@ static int unixShmOpen( const char *zName, /* Name of file to mmap */ sqlite3_shm **pShm /* Write the unixShm object created here */ ){ - struct unixShm *p = 0; - struct unixShmFile *pFile = 0; - int rc; - struct unixFileId fid; - struct stat sStat; + struct unixShm *p = 0; /* The connection to be opened */ + struct unixShmFile *pFile = 0; /* The underlying mmapped file */ + int rc; /* Result code */ + struct unixFileId fid; /* Unix file identifier */ + struct stat sStat; /* Result from stat() an fstat() */ + /* Allocate space for the new sqlite3_shm object */ p = sqlite3_malloc( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM; memset(p, 0, sizeof(*p)); + /* Look to see if there is an existing unixShmFile that can be used. + ** If no matching unixShmFile currently exists, create a new one. + */ unixEnterMutex(); rc = stat(zName, &sStat); if( rc==0 ){ @@ -4982,16 +4998,27 @@ static int unixShmOpen( pFile->fid.ino = sStat.st_ino; pFile->size = (int)sStat.st_size; pFile->size = (pFile->size/SQLITE_UNIX_SHM_INCR)*SQLITE_UNIX_SHM_INCR; - if( pFile->size==0 ){ - pFile->size = SQLITE_UNIX_SHM_INCR; - rc = ftruncate(pFile->h, pFile->size); - if( rc ){ - rc = SQLITE_FULL; + + /* Check to see if another process is holding the dead-man switch. + ** If not, truncate the file to zero length. + */ + if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_MUTEX) ){ + rc = SQLITE_IOERR_LOCK; + goto shm_open_err; + } + if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){ + if( ftruncate(pFile->h, 0) ){ + rc = SQLITE_IOERR; goto shm_open_err; } + pFile->size = 0; } + rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS); + if( rc ) goto shm_open_err; + unixShmSystemLock(pFile, F_UNLCK, UNIX_SHM_MUTEX); } + /* Make the new connection a child of the unixShmFile */ p->pFile = pFile; p->pNext = pFile->pFirst; #ifdef SQLITE_DEBUG @@ -5003,6 +5030,7 @@ static int unixShmOpen( unixLeaveMutex(); return SQLITE_OK; + /* Jump here on any error */ shm_open_err: unixShmPurge(); sqlite3_free(p);