aboutsummaryrefslogtreecommitdiff
path: root/src/btree.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-04-30 13:30:32 +0000
committerdrh <drh@noemail.net>2009-04-30 13:30:32 +0000
commitc47fd8e031a411a66d1c57833c35a3db37cec476 (patch)
tree6e6e4acb06400663d397c24e89fa4b3ff356e92d /src/btree.c
parent9b3c24d15d2336db21d3bbafcaf6268f4e170eef (diff)
downloadsqlite-c47fd8e031a411a66d1c57833c35a3db37cec476.tar.gz
sqlite-c47fd8e031a411a66d1c57833c35a3db37cec476.zip
Disallow attaching the same database multiple times to the same db connection
in shared cache mode, since doing so leads to deadlock. (CVS 6578) FossilOrigin-Name: 715f14f1dcaf604d4794bf3e18e245d4f8c5d5a9
Diffstat (limited to 'src/btree.c')
-rw-r--r--src/btree.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/btree.c b/src/btree.c
index 315991eb5..acc4aaadd 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.601 2009/04/30 09:10:38 danielk1977 Exp $
+** $Id: btree.c,v 1.602 2009/04/30 13:30:33 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -1401,6 +1401,12 @@ static int btreeInvokeBusyHandler(void *pArg){
** database file will be deleted when sqlite3BtreeClose() is called.
** If zFilename is ":memory:" then an in-memory database is created
** that is automatically destroyed when it is closed.
+**
+** If the database is already opened in the same database connection
+** and we are in shared cache mode, then the open will fail with an
+** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
+** objects in the same database connection since doing so will lead
+** to problems with locking.
*/
int sqlite3BtreeOpen(
const char *zFilename, /* Name of the file containing the BTree database */
@@ -1466,6 +1472,17 @@ int sqlite3BtreeOpen(
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
+ int iDb;
+ for(iDb=db->nDb-1; iDb>=0; iDb--){
+ Btree *pExisting = db->aDb[iDb].pBt;
+ if( pExisting && pExisting->pBt==pBt ){
+ sqlite3_mutex_leave(mutexShared);
+ sqlite3_mutex_leave(mutexOpen);
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return SQLITE_CONSTRAINT;
+ }
+ }
p->pBt = pBt;
pBt->nRef++;
break;