Index: ext/lsm1/lsm_shared.c ================================================================== --- ext/lsm1/lsm_shared.c +++ ext/lsm1/lsm_shared.c @@ -250,10 +250,12 @@ }else{ /* Block for an exclusive lock on DMS1. This lock serializes all calls ** to doDbConnect() and doDbDisconnect() across all processes. */ rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1); if( rc==LSM_OK ){ + + lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0); /* Try an exclusive lock on DMS2. If successful, this is the last ** connection to the database. In this case flush the contents of the ** in-memory tree to disk and write a checkpoint. */ rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 1, LSM_LOCK_EXCL); @@ -322,11 +324,10 @@ if( pDb->iRwclient>=0 ){ lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0); pDb->iRwclient = -1; } - lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0); lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0); } pDb->pShmhdr = 0; } @@ -475,12 +476,19 @@ int bReadonly = (pDb->bReadonly && pDb->bMultiProc); rc = dbOpenSharedFd(pDb->pEnv, p, bReadonly); } if( rc==LSM_OK && p->bMultiProc==0 ){ + /* Hold an exclusive lock DMS1 while grabbing DMS2. This ensures + ** that any ongoing call to doDbDisconnect() (even one in another + ** process) is finished before proceeding. */ assert( p->bReadonly==0 ); - rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS2, LSM_LOCK_EXCL); + rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_EXCL); + if( rc==LSM_OK ){ + rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS2, LSM_LOCK_EXCL); + lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK); + } } if( rc==LSM_OK ){ p->pDbNext = gShared.pDatabase; gShared.pDatabase = p; @@ -1745,11 +1753,14 @@ if( eOp==LSM_LOCK_EXCL ) mask |= ((u64)1 << (iLock+32-1)); } lsmMutexEnter(db->pEnv, p->pClientMutex); for(pIter=p->pConn; pIter; pIter=pIter->pNext){ - if( pIter!=db && (pIter->mLock & mask) ) break; + if( pIter!=db && (pIter->mLock & mask) ){ + assert( pIter!=db ); + break; + } } if( pIter ){ rc = LSM_BUSY; }else if( p->bMultiProc ){